home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / XLIBP202.ZIP / XBM2.ASM < prev    next >
Assembly Source File  |  1994-12-08  |  91KB  |  2,865 lines

  1. ; ***************************************************************************
  2. ; **                             XLibPas v2.0                              **
  3. ; **                        for Borland Pascal 7.0                         **
  4. ; **                                  by                                   **
  5. ; **                            Tristan Tarrant                            **
  6. ; ***************************************************************************
  7. ; ** Credits :                                                             **
  8. ; **   Michael Abrash    - Concepts, Algorithms                            **
  9. ; **   Themie Gouthas    - Main code and implementation                    **
  10. ; **   Matthew MacKenzie - Compiled Bitmaps, Circles, etc.                 **
  11. ; **   Tore Bastiansen   - Virtual VSync Handler                           **
  12. ; ***************************************************************************
  13.  
  14.         .MODEL TPASCAL
  15.         .386
  16.         LOCALS
  17.  
  18. include xlib2.inc
  19. include xbm2.inc
  20.  
  21.         .CODE
  22.  
  23. xpbmtobm proc far srcpbm:dword,destbm:dword
  24.  
  25.     push ds
  26.     push di
  27.     push si
  28.  
  29.     les  di,[destbm]        ; es:di -> destination bitmap
  30.     lds  si,[srcpbm]        ; ds:si -> source planar bitmap
  31.     lodsb                 ; load AL with source pbm pixel width per plane
  32.     mov  bl,al            ; save in CL
  33.     xor  ah,ah            ; convert to word
  34.     shl  ax,2             ; mult by 4 giving source image width
  35.     cmp  ax,255           ; if the result > 255 then we have exceeded
  36.     ja   @@WidthError     ; the max width of linear bm.
  37.  
  38.     stosb                 ; write do destbm
  39.  
  40.     lodsb                 ; tranfer source pbm height in pixels to
  41.     stosb                           ;  destbm
  42.  
  43.     xor  ah,ah            ; convert to word
  44.     mul  bl               ; AX = AX * BL ie. total no. pixels per plane
  45.     mov  dx,di            ; save DI, the pointer to the destination bm
  46.     mov  bl,3             ; set plane loop counter (BL)
  47.  
  48. @@PlaneLoop:
  49.     mov  cx,ax            ; set CX to total number of pixels per plane
  50.  
  51. @@PixelLoop:
  52.     movsb                 ; transfer pixel
  53.     add  di,3             ; increment destination to compensate for plane
  54.     loop @@PixelLoop
  55.  
  56.     inc  dx               ; increment original di for next pixel plane
  57.     mov  di,dx            ; and restore di from incremented original
  58.     dec  bl               ; decrement plane counter
  59.     jns  @@PlaneLoop      ; loop if more planes left
  60.     xor  ax,ax
  61.     jmp  short @@Done
  62. @@WidthError:
  63.     mov  ax,1
  64.  
  65. @@Done:
  66.     pop  si
  67.     pop  di
  68.     pop  ds
  69.     ret
  70. xpbmtobm endp
  71.  
  72.  
  73. xbmtopbm proc far srcbm:dword,destpbm:dword
  74.     push ds
  75.     push di
  76.     push si
  77.  
  78.     les  di,[destpbm]        ; es:di -> destination planar bitmap
  79.     lds  si,[srcbm]          ; ds:si -> source bitmap
  80.     lodsb                    ; load AX with source bitmap width
  81.     test al,03h              ; Check that width is a multiple of 4
  82.     jnz  @@WidthIncompatible
  83.     shr  al,2                ; divide by 4 giving width of plane
  84.     stosb                    ; store destination planar bitmap width
  85.     mov  bl,al               ;  and copy to bl
  86.     lodsb
  87.     stosb                    ; Transfer source bitmap height to dest pbm
  88.     xor  ah,ah               ; Conver height to word
  89.     mul  bl                  ; calculate the total no. of pixels / plane
  90.     mov  dx,si               ; save source offset
  91.     mov  bl,3
  92.  
  93. @@PlaneLoop:
  94.     mov  cx,ax               ; set CX to total number of pixels per plane
  95.  
  96. @@PixelLoop:
  97.     movsb                    ; transfer pixel
  98.     add  si,3                ; increment src offset to compensate for plane
  99.     loop @@PixelLoop
  100.  
  101.     inc  dx                  ; increment original si for next pixel plane
  102.     mov  si,dx               ; and restore si from incremented original
  103.     dec  bl                  ; decrement plane counter
  104.     jns  @@PlaneLoop         ; loop if more planes left
  105.     xor  ax,ax
  106.     jmp  short @@Done
  107. @@WidthIncompatible:
  108.     mov  ax,1
  109.  
  110. @@Done:
  111.     pop  si
  112.     pop  di
  113.     pop  ds
  114.     ret
  115. xbmtopbm endp
  116.  
  117. xcompilebitmap proc far logicalwidth:word,bitmap:dword,output:dword
  118. LOCAL bwidth,scanx,scany,outputx,outputy,column,setcolumn,inputsize:word
  119.     push si
  120.     push di
  121.     push ds
  122.  
  123.     mov word ptr [scanx],0
  124.     mov word ptr [scany],0
  125.     mov word ptr [outputx],0
  126.     mov word ptr [outputy],0
  127.     mov word ptr [column],0
  128.     mov word ptr [setcolumn],0
  129.  
  130.     lds si,[bitmap]     ; 32-bit pointer to source bitmap
  131.  
  132.     les di,[output]     ; 32-bit pointer to destination stream
  133.  
  134.     lodsb               ; load width byte
  135.     xor ah, ah          ; convert to word
  136.     mov [bwidth], ax    ; save for future reference
  137.     mov bl, al          ; copy width byte to bl
  138.     lodsb               ; load height byte -- already a word since ah=0
  139.     mul bl              ; mult height word by width byte
  140.     mov [inputsize], ax;  to get pixel total
  141.  
  142. @@MainLoop:
  143.     mov bx, [scanx]     ; position in original bitmap
  144.     add bx, [scany]
  145.  
  146.     mov al, [si+bx]     ; get pixel
  147.     or  al, al          ; skip empty pixels
  148.     jnz @@NoAdvance
  149.     jmp @@Advance
  150. @@NoAdvance:
  151.  
  152.     mov dx, [setcolumn]
  153.     cmp dx, [column]
  154.     je @@SameColumn
  155. @@ColumnLoop:
  156.     Emitw ROLAL        ; emit code to move to new column
  157.     Emitw ADCSIIMMED
  158.     Emitb 0
  159.  
  160.     inc dx
  161.     cmp dx, [column]
  162.     jl @@ColumnLoop
  163.  
  164.     Emitb OUTAL        ; emit code to set VGA mask for new column
  165.     mov [setcolumn], dx
  166. @@SameColumn:
  167.     mov dx, [outputy]   ; calculate output position
  168.     add dx, [outputx]
  169.     sub dx, 128
  170.  
  171.     add word ptr [scanx], 4
  172.     mov cx, [scanx]     ; within four pixels of right edge?
  173.     cmp cx, [bwidth]
  174.     jge @@OnePixel
  175.  
  176.     inc word ptr [outputx]
  177.     mov ah, [si+bx+4]   ; get second pixel
  178.     or ah, ah
  179.     jnz @@TwoPixels
  180. @@OnePixel:
  181.     cmp dx, 127         ; can we use shorter form?
  182.     jg @@OnePixLarge
  183.     cmp dx, -128
  184.     jl @@OnePixLarge
  185.     Emitw SHORTSTORE8
  186.     Emitb dl            ; 8-bit position in output
  187.     jmp @@EmitOnePixel
  188. @@OnePixLarge:
  189.     Emitw STORE8
  190.     Emitw dx            ; position in output
  191. @@EmitOnePixel:
  192.     Emitb al
  193.     jmp short @@Advance
  194. @@TwoPixels:
  195.     cmp dx, 127
  196.     jg @@TwoPixLarge
  197.     cmp dx, -128
  198.     jl @@TwoPixLarge
  199.     Emitw SHORTSTORE16
  200.     Emitb dl            ; 8-bit position in output
  201.     jmp @@EmitTwoPixels
  202. @@TwoPixLarge:
  203.     Emitw STORE16
  204.     Emitw dx            ; position in output
  205. @@EmitTwoPixels:
  206.     Emitw ax
  207.  
  208. @@Advance:
  209.     inc word ptr [outputx]
  210.     mov ax, [scanx]
  211.     add ax, 4
  212.     cmp ax, [bwidth]
  213.     jl @@AdvanceDone
  214.     mov dx, [outputy]
  215.     add dx, [logicalwidth]
  216.     mov cx, [scany]
  217.     add cx, [bwidth]
  218.     cmp cx, [inputsize]
  219.     jl @@NoNewColumn
  220.     inc word ptr [column]
  221.     mov cx, [column]
  222.     cmp cx, 4
  223.     je @@Exit           ; Column 4: there is no column 4.
  224.     xor cx, cx          ; scany and outputy are 0 again for
  225.     mov dx, cx          ; the new column
  226. @@NoNewColumn:
  227.     mov [outputy], dx
  228.     mov [scany], cx
  229.     mov word ptr [outputx], 0
  230.     mov ax,[column]
  231. @@AdvanceDone:
  232.     mov [scanx], ax
  233.     jmp @@MainLoop
  234.  
  235. @@Exit:
  236.     Emitb RETURN
  237.     mov ax,di
  238.     sub ax,word ptr [output] ; size of generated code
  239.  
  240.     pop ds
  241.     pop di
  242.     pop si
  243.     ret
  244. xcompilebitmap endp
  245.  
  246.  
  247. xsizeofcbitmap proc far logicalwidth:word,bitmap:dword
  248. LOCAL bwidth,scanx,scany,outputx,outputy,column,setcolumn,inputsize:word
  249.     push si
  250.     push di
  251.     push ds
  252.  
  253.     mov word ptr [scanx], 0
  254.     mov word ptr [scany], 0
  255.     mov word ptr [outputx], 0
  256.     mov word ptr [outputy], 0
  257.     mov word ptr [column], 0
  258.     mov word ptr [setcolumn], 0
  259.  
  260.     lds si,[bitmap]     ; 32-bit pointer to source bitmap
  261.  
  262.     mov di, 1           ; initial size is just the size of the far RET
  263.  
  264.     lodsb               ; load width byte
  265.     xor ah, ah          ; convert to word
  266.     mov [bwidth], ax    ; save for future reference
  267.     mov bl, al          ; copy width byte to bl
  268.     lodsb               ; load height byte -- already a word since ah=0
  269.     mul bl              ; mult height word by width byte
  270.     mov [inputsize], ax;  to get pixel total
  271.  
  272. @@MainLoop:
  273.     mov bx, [scanx]     ; position in original bitmap
  274.     add bx, [scany]
  275.  
  276.     mov al, [si+bx]     ; get pixel
  277.     or  al, al          ; skip empty pixels
  278.     jnz @@NoAdvance
  279.     jmp @@Advance
  280. @@NoAdvance:
  281.  
  282.     mov dx, [setcolumn]
  283.     cmp dx, [column]
  284.     je @@SameColumn
  285. @@ColumnLoop:
  286.     add di, 5           ; size of code to move to new column
  287.     inc dx
  288.     cmp dx,[column]
  289.     jl @@ColumnLoop
  290.  
  291.     inc di              ; size of code to set VGA mask
  292.     mov [setcolumn], dx
  293. @@SameColumn:
  294.     mov dx, [outputy]   ; calculate output position
  295.     add dx, [outputx]
  296.     sub dx, 128
  297.  
  298.     add word ptr [scanx], 4
  299.     mov cx, [scanx]     ; within four pixels of right edge?
  300.     cmp cx, [bwidth]
  301.     jge @@OnePixel
  302.  
  303.     inc word ptr [outputx]
  304.     mov ah,[si+bx+4]    ; get second pixel
  305.     or ah, ah
  306.     jnz @@TwoPixels
  307. @@OnePixel:
  308.     cmp dx, 127         ; can we use shorter form?
  309.     jg @@OnePixLarge
  310.     cmp dx, -128
  311.     jl @@OnePixLarge
  312.     add di, 4           ; size of 8-bit position in output plus one pixel
  313.     jmp @@EmitOnePixel
  314. @@OnePixLarge:
  315.     add di, 5           ; size of position in output plus one pixels
  316. @@EmitOnePixel:
  317.     jmp short @@Advance
  318. @@TwoPixels:
  319.     cmp dx, 127
  320.     jg @@TwoPixLarge
  321.     cmp dx, -128
  322.     jl @@TwoPixLarge
  323.     add di, 5           ; size of 8-bit position in output plus two pixels
  324.     jmp @@EmitTwoPixels
  325. @@TwoPixLarge:
  326.     add di, 6           ; size of 16-bit position in output plus two pixels
  327. @@EmitTwoPixels:
  328.  
  329. @@Advance:
  330.     inc word ptr [outputx]
  331.     mov ax, [scanx]
  332.     add ax,4
  333.     cmp ax, [bwidth]
  334.     jl @@AdvanceDone
  335.     mov dx, [outputy]
  336.     add dx, [logicalwidth]
  337.     mov cx, [scany]
  338.     add cx, [bwidth]
  339.     cmp cx, [inputsize]
  340.     jl @@NoNewColumn
  341.     inc word ptr [column]
  342.     mov cx, [column]
  343.     cmp cx, 4
  344.     je @@Exit           ; Column 4: there is no column 4.
  345.     xor cx,cx           ; scany and outputy are 0 again for
  346.     mov dx,cx           ; the new column
  347. @@NoNewColumn:
  348.     mov [outputy], dx
  349.     mov [scany], cx
  350.     mov word ptr [outputx], 0
  351.     mov ax,[column]
  352. @@AdvanceDone:
  353.     mov [scanx], ax
  354.     jmp @@MainLoop
  355.  
  356. @@Exit:
  357.     mov ax, di          ; size of generated code
  358.  
  359.     pop ds
  360.     pop di
  361.     pop si
  362.     ret
  363. xsizeofcbitmap endp
  364.  
  365. xputcbitmap proc far XPos:word,YPos:word,PageOffset:word,Sprite:dword
  366.  
  367.     push ds
  368.     mov cx, [SelectorInc]
  369.     mov ax, [ScrnLogicalByteWidth] ; global Xlib variable
  370.     mul word ptr [YPos] ; height in bytes
  371.     mov si, [XPos]
  372.     mov bx, si
  373.     sar si, 2           ; width in bytes
  374.     add si, ax
  375.     add si, [PageOffset]; (YPos * screen width) +
  376.     add si, 128         ;   (Xpos / 4) + page base + 128 ==> starting pos
  377.  
  378.     and bx, 3
  379.     mov ah, ColumnMask[bx]
  380.  
  381.     mov dx, SCINDEX
  382.     mov al, MAPMASK
  383.     out dx, ax
  384.     inc dx              ; ready to send out other masks as bytes
  385.     mov al, ah
  386.     mov bx, SCREENSEG
  387.     mov ds, bx          ; We do this so the compiled shape won't need
  388.                                             ; segment overrides.
  389.     call dword ptr [Sprite] ; the business end of the routine
  390.     pop ds
  391.  
  392.     ret
  393. xputcbitmap endp
  394.  
  395.  
  396. xcompilepbm proc far logicalwidth:word,bitmap:dword,output:dword
  397. LOCAL bwidth,scanx,scany,outputx,outputy,column,setcolumn,inputsize:word
  398.     push si
  399.     push di
  400.     push ds
  401.  
  402.     mov word ptr [scanx],0
  403.     mov word ptr [scany],0
  404.     mov word ptr [outputx],0
  405.     mov word ptr [outputy],0
  406.     mov word ptr [column],0
  407.     mov word ptr [setcolumn],0
  408.  
  409.     lds si,[bitmap]     ; 32-bit pointer to source bitmap
  410.  
  411.     les di,[output]     ; 32-bit pointer to destination stream
  412.  
  413.     lodsb               ; load width byte
  414.     xor ah, ah          ; convert to word
  415.     mov [bwidth], ax    ; save for future reference
  416.     mov bl, al          ; copy width byte to bl
  417.     lodsb               ; load height byte -- already a word since ah=0
  418.     mul bl              ; mult height word by width byte
  419.     mov [inputsize], ax;  to get pixel total
  420.  
  421. @@MainLoop:
  422.     mov bx, [scanx]     ; position in original bitmap
  423.     add bx, [scany]
  424.  
  425.     mov al, [si+bx]     ; get pixel
  426.     or  al, al          ; skip empty pixels
  427.     jnz @@NoAdvance
  428.     jmp @@Advance
  429. @@NoAdvance:
  430.  
  431.     mov dx, [setcolumn]
  432.     cmp dx, [column]
  433.     je @@SameColumn
  434. @@ColumnLoop:
  435.     Emitw ROLAL        ; emit code to move to new column
  436.     Emitw ADCSIIMMED
  437.     Emitb 0
  438.  
  439.     inc dx
  440.     cmp dx, [column]
  441.     jl @@ColumnLoop
  442.  
  443.     Emitb OUTAL        ; emit code to set VGA mask for new column
  444.     mov [setcolumn], dx
  445. @@SameColumn:
  446.     mov dx, [outputy]   ; calculate output position
  447.     add dx, [outputx]
  448.     sub dx, 128
  449.  
  450.     inc word ptr [scanx]
  451.     mov cx, [scanx]     ; within four pixels of right edge?
  452.     cmp cx, [bwidth]
  453.     jge @@OnePixel
  454.  
  455.     inc word ptr [outputx]
  456.     mov ah, [si+bx+1]   ; get second pixel
  457.     or ah, ah
  458.     jnz @@TwoPixels
  459. @@OnePixel:
  460.     cmp dx, 127         ; can we use shorter form?
  461.     jg @@OnePixLarge
  462.     cmp dx, -128
  463.     jl @@OnePixLarge
  464.     Emitw SHORTSTORE8
  465.     Emitb dl            ; 8-bit position in output
  466.     jmp @@EmitOnePixel
  467. @@OnePixLarge:
  468.     Emitw STORE8
  469.     Emitw dx            ; position in output
  470. @@EmitOnePixel:
  471.     Emitb al
  472.     jmp short @@Advance
  473. @@TwoPixels:
  474.     cmp dx, 127
  475.     jg @@TwoPixLarge
  476.     cmp dx, -128
  477.     jl @@TwoPixLarge
  478.     Emitw SHORTSTORE16
  479.     Emitb dl            ; 8-bit position in output
  480.     jmp @@EmitTwoPixels
  481. @@TwoPixLarge:
  482.     Emitw STORE16
  483.     Emitw dx            ; position in output
  484. @@EmitTwoPixels:
  485.     Emitw ax
  486.  
  487. @@Advance:
  488.     inc word ptr [outputx]
  489.     mov ax, [scanx]
  490.     inc ax
  491.     cmp ax, [bwidth]
  492.     jl @@AdvanceDone
  493.     mov dx, [outputy]
  494.     add dx, [logicalwidth]
  495.     mov cx, [scany]
  496.     add cx, [bwidth]
  497.     cmp cx, [inputsize]
  498.     jl @@NoNewColumn
  499.     inc word ptr [column]
  500.     mov cx, [column]
  501.     cmp cx, 4
  502.     je @@Exit           ; Column 4: there is no column 4.
  503.     xor cx, cx          ; scany and outputy are 0 again for
  504.     mov dx, cx          ; the new column
  505.     add si, [inputsize]
  506. @@NoNewColumn:
  507.     mov [outputy], dx
  508.     mov [scany], cx
  509.     xor ax, ax
  510.     mov word ptr [outputx], 0
  511. @@AdvanceDone:
  512.     mov [scanx], ax
  513.     jmp @@MainLoop
  514.  
  515. @@Exit:
  516.     Emitb RETURN
  517.     mov ax,di
  518.     sub ax,word ptr [output] ; size of generated code
  519.  
  520.     pop ds
  521.     pop di
  522.     pop si
  523.     ret
  524. xcompilepbm endp
  525.  
  526.  
  527. xsizeofcpbm proc far logicalwidth:word,bitmap:dword
  528. LOCAL bwidth,scanx,scany,outputx,outputy,column,setcolumn,inputsize:word
  529.     push si
  530.     push di
  531.     push ds
  532.  
  533.     mov word ptr [scanx], 0
  534.     mov word ptr [scany], 0
  535.     mov word ptr [outputx], 0
  536.     mov word ptr [outputy], 0
  537.     mov word ptr [column], 0
  538.     mov word ptr [setcolumn], 0
  539.  
  540.     lds si,[bitmap]     ; 32-bit pointer to source bitmap
  541.  
  542.     mov di, 1           ; initial size is just the size of the far RET
  543.  
  544.     lodsb               ; load width byte
  545.     xor ah, ah          ; convert to word
  546.     mov [bwidth], ax    ; save for future reference
  547.     mov bl, al          ; copy width byte to bl
  548.     lodsb               ; load height byte -- already a word since ah=0
  549.     mul bl              ; mult height word by width byte
  550.     mov [inputsize], ax;  to get pixel total
  551.  
  552. @@MainLoop:
  553.     mov bx, [scanx]     ; position in original bitmap
  554.     add bx, [scany]
  555.  
  556.     mov al, [si+bx]     ; get pixel
  557.     or  al, al          ; skip empty pixels
  558.     jnz @@NoAdvance
  559.     jmp @@Advance
  560. @@NoAdvance:
  561.  
  562.     mov dx, [setcolumn]
  563.     cmp dx, [column]
  564.     je @@SameColumn
  565. @@ColumnLoop:
  566.     add di, 5           ; size of code to move to new column
  567.     inc dx
  568.     cmp dx,[column]
  569.     jl @@ColumnLoop
  570.  
  571.     inc di              ; size of code to set VGA mask
  572.     mov [setcolumn], dx
  573. @@SameColumn:
  574.     mov dx, [outputy]   ; calculate output position
  575.     add dx, [outputx]
  576.     sub dx, 128
  577.  
  578.     inc word ptr [scanx]
  579.     mov cx, [scanx]     ; within four pixels of right edge?
  580.     cmp cx, [bwidth]
  581.     jge @@OnePixel
  582.  
  583.     inc word ptr [outputx]
  584.     mov ah,[si+bx+1]    ; get second pixel
  585.     or ah, ah
  586.     jnz @@TwoPixels
  587. @@OnePixel:
  588.     cmp dx, 127         ; can we use shorter form?
  589.     jg @@OnePixLarge
  590.     cmp dx, -128
  591.     jl @@OnePixLarge
  592.     add di, 4           ; size of 8-bit position in output plus one pixel
  593.     jmp @@EmitOnePixel
  594. @@OnePixLarge:
  595.     add di, 5           ; size of position in output plus one pixels
  596. @@EmitOnePixel:
  597.     jmp short @@Advance
  598. @@TwoPixels:
  599.     cmp dx, 127
  600.     jg @@TwoPixLarge
  601.     cmp dx, -128
  602.     jl @@TwoPixLarge
  603.     add di, 5           ; size of 8-bit position in output plus two pixels
  604.     jmp @@EmitTwoPixels
  605. @@TwoPixLarge:
  606.     add di, 6           ; size of 16-bit position in output plus two pixels
  607. @@EmitTwoPixels:
  608.  
  609. @@Advance:
  610.     inc word ptr [outputx]
  611.     mov ax, [scanx]
  612.     inc ax
  613.     cmp ax, [bwidth]
  614.     jl @@AdvanceDone
  615.     mov dx, [outputy]
  616.     add dx, [logicalwidth]
  617.     mov cx, [scany]
  618.     add cx, [bwidth]
  619.     cmp cx, [inputsize]
  620.     jl @@NoNewColumn
  621.     inc word ptr [column]
  622.     mov cx, [column]
  623.     cmp cx, 4
  624.     je @@Exit           ; Column 4: there is no column 4.
  625.     xor cx,cx           ; scany and outputy are 0 again for
  626.     mov dx,cx           ; the new column
  627.     add si, [inputsize]
  628. @@NoNewColumn:
  629.     mov [outputy], dx
  630.     mov [scany], cx
  631.     xor ax, ax
  632.     mov word ptr [outputx], ax
  633. @@AdvanceDone:
  634.     mov [scanx], ax
  635.     jmp @@MainLoop
  636.  
  637. @@Exit:
  638.     mov ax, di          ; size of generated code
  639.  
  640.     pop ds
  641.     pop di
  642.     pop si
  643.     ret
  644. xsizeofcpbm endp
  645.  
  646. xflipmaskedpbm  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word
  647. LOCAL Plane:byte,BMHeight:byte,LineInc:word
  648.  
  649.     push  si
  650.     push  di
  651.     push  ds
  652.     cld
  653.     mov   ax,SCREENSEG
  654.     mov   es,ax
  655.     mov   ax,[Y]                      ; Calculate dest screen row
  656.     mov   bx,[ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen
  657.     mul   bx                          ;  width then adding screen offset
  658.     mov   di,[ScrnOffs]               ;  store result in DI
  659.     add   di,ax
  660.     mov   cx,[X]                      ; Load X coord into CX and make a
  661.     mov   dx,cx                       ;  copy in DX
  662.     shr   dx,2                        ; Find starting byte in dest row
  663.     add   di,dx                       ;  add to DI giving screen offset of
  664.                                                                                     ;  first pixel's byte
  665.     lds   si,[Bitmap]                 ; DS:SI -> Bitmap data
  666.     lodsw                             ; Al = B.M. width (bytes) AH = B.M.
  667.                                                                                     ;  height
  668.     cmp   Orientation,0
  669.     jz    UnFlippedMasked
  670.  
  671.     mov   [BMHeight],ah               ; Save source bitmap dimensions
  672.                 xor   ah,ah                       ; LineInc = bytes to the begin.
  673.     add   bx,ax                       ;  of bitmaps next row on screen
  674.     mov   [LineInc],bx
  675.     mov   bh,al                       ; Use bh as column loop count
  676.                 and   cx,0003h                    ; mask X coord giving plane of 1st
  677.                         ; bitmap pixel(zero CH coincidentally)
  678.     mov   ah,11h                      ; Init. mask for VGA plane selection
  679.     shl   ah,cl                       ; Shift for starting pixel plane
  680.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  681.     mov   al,MAPMASK
  682.     out   dx,al
  683.     inc   dx
  684.     mov   [Plane],4                   ; Set plane counter to 4
  685. @@PlaneLoop:
  686.     push  di                          ; Save bitmap's start dest. offset
  687.     mov   bl,[BMHeight]               ; Reset row counter (BL)
  688.     mov   al,ah
  689.     out   dx,al                       ; set vga write plane
  690. @@RowLoop:
  691.     mov   cl,bh                       ; Reset Column counter cl
  692. @@ColLoop:
  693.     lodsb                             ; Get next source bitmap byte
  694.     or    al,al                       ; If not zero then write to dest.
  695.     jz    @@NoPixel                   ; otherwise skip to next byte
  696.     mov   es:[di],al
  697. @@NoPixel:
  698.     dec   di
  699.     loop  @@ColLoop                   ; loop if more columns left
  700.     add   di,[LineInc]                ; Move to next row
  701.     dec   bl                          ; decrement row counter
  702.     jnz   @@RowLoop                   ; Jump if more rows left
  703.     pop   di                          ; Restore bitmaps start dest byte
  704.     ror   ah,1                        ; Shift mask for next plane
  705.     sbb   di,0                        ; If wrapped increment dest address
  706.     dec   [Plane]                     ; Decrement plane counter
  707.     jnz   @@PlaneLoop                 ; Jump if more planes left
  708.  
  709.     pop   ds                          ; restore data segment
  710.     pop   di                          ; restore registers
  711.     pop   si
  712.     ret
  713. xflipmaskedpbm  endp
  714.  
  715.  
  716. xputmaskedpbm  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  717. LOCAL Plane:byte,BMHeight:byte,LineInc:word
  718.     push  si
  719.     push  di
  720.     push  ds
  721.     cld
  722.     mov   ax,SCREENSEG
  723.     mov   es,ax
  724.     mov   ax,Y                      ; Calculate dest screen row
  725.     mov   bx,ScrnLogicalByteWidth  ;  by mult. dest Y coord by Screen
  726.     mul   bx                          ;  width then adding screen offset
  727.     mov   di,[ScrnOffs]               ;  store result in DI
  728.     add   di,ax
  729.     mov   cx,[X]                      ; Load X coord into CX and make a
  730.     mov   dx,cx                       ;  copy in DX
  731.     shr   dx,2                        ; Find starting byte in dest row
  732.     add   di,dx                       ;  add to DI giving screen offset of
  733.                                                                                     ;  first pixel's byte
  734.     lds   si,[Bitmap]                 ; DS:SI -> Bitmap data
  735.     lodsw                             ; Al = B.M. width (bytes) AH = B.M.
  736.                                                                                     ;  height
  737. UnFlippedMasked:
  738.     mov   [BMHeight],ah               ; Save source bitmap dimensions
  739.     xor   ah,ah                       ; LineInc = bytes to the begin.
  740.     sub   bx,ax                       ;  of bitmaps next row on screen
  741.     mov   [LineInc],bx
  742.     mov   bh,al                       ; Use bh as column loop count
  743.     and   cx,0003h                    ; mask X coord giving plane of 1st
  744.                                                                         ; bitmap pixel(zero CH coincidentally)
  745.     mov   ah,11h                      ; Init. mask for VGA plane selection
  746.     shl   ah,cl                       ; Shift for starting pixel plane
  747.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  748.     mov   al,MAPMASK
  749.     out   dx,al
  750.     inc   dx
  751.     mov   [Plane],4                   ; Set plane counter to 4
  752. @@PlaneLoop:
  753.     push  di                          ; Save bitmap's start dest. offset
  754.     mov   bl,[BMHeight]               ; Reset row counter (BL)
  755.     mov   al,ah
  756.     out   dx,al                       ; set vga write plane
  757. @@RowLoop:
  758.     mov   cl,bh                       ; Reset Column counter cl
  759. @@ColLoop:
  760.     lodsb                             ; Get next source bitmap byte
  761.     or    al,al                       ; If not zero then write to dest.
  762.     jz    @@NoPixel                   ; otherwise skip to next byte
  763.     mov   es:[di],al
  764. @@NoPixel:
  765.     inc   di
  766.     loop  @@ColLoop                   ; loop if more columns left
  767.     add   di,[LineInc]                ; Move to next row
  768.     dec   bl                          ; decrement row counter
  769.     jnz   @@RowLoop                   ; Jump if more rows left
  770.     pop   di                          ; Restore bitmaps start dest byte
  771.     rol   ah,1                        ; Shift mask for next plane
  772.     adc   di,0                        ; If wrapped increment dest address
  773.     dec   [Plane]                     ; Decrement plane counter
  774.     jnz   @@PlaneLoop                 ; Jump if more planes left
  775.  
  776.     pop   ds                          ; restore data segment
  777.     pop   di                          ; restore registers
  778.     pop   si
  779.     ret
  780. xputmaskedpbm  endp
  781.  
  782. xputpbm  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  783. LOCAL Plane:byte,BMHeight:byte,LineInc:word
  784.     push  si
  785.     push  di
  786.     push  ds
  787.     cld
  788.     mov   ax,SCREENSEG
  789.     mov   es,ax
  790.     mov   ax,[Y]                      ; Calculate dest screen row
  791.     mov   bx,[ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen
  792.     mul   bx                          ;  width then adding screen offset
  793.     mov   di,[ScrnOffs]               ;  store result in DI
  794.     add   di,ax
  795.     mov   cx,[X]                      ; Load X coord into CX and make a
  796.     mov   dx,cx                       ;  copy in DX
  797.     shr   dx,2                        ; Find starting byte in dest row
  798.     add   di,dx                       ;  add to DI giving screen offset of
  799.                                                                                     ;  first pixel's byte
  800.     lds   si,[Bitmap]                 ; DS:SI -> Bitmap data
  801.     lodsw                             ; Al = B.M. width (bytes) AH = B.M.
  802.                                                                                     ;  height
  803. UnFlipped:
  804.     mov   [BMHeight],ah               ; Save source bitmap dimensions
  805.     xor   ah,ah                       ; LineInc = bytes to the begin.
  806.     sub   bx,ax                       ;  of bitmaps next row on screen
  807.     mov   [LineInc],bx
  808.     mov   bh,al
  809.                                                                         ; Self Modifying, Shame, shame shame..
  810.     and   cx,0003h                    ; mask X coord giving plane of 1st
  811.                                                                         ; bitmap pixel(zero CH coincidentally)
  812.     mov   ah,11h                      ; Init. mask for VGA plane selection
  813.     shl   ah,cl                       ; Shift for starting pixel plane
  814.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  815.     mov   al,MAPMASK
  816.     out   dx,al
  817.     inc   dx
  818.     mov   [Plane],4                   ; Set plane counter to 4
  819. @@PlaneLoop:
  820.     push  di
  821.     mov   bl,[BMHeight]
  822.     mov   al,ah
  823.     out   dx,al
  824. @@RowLoop:
  825.     mov   cl,bh
  826.     shr   cl,1
  827.     rep   movsw                       ; Copy a complete row for curr plane
  828.     adc   cl,0
  829.     rep   movsb
  830.     add   di,[LineInc]                ; Move to next row
  831.     dec   bl                          ; decrement row counter
  832.     jnz   @@RowLoop                   ; Jump if more rows left
  833.     pop   di                          ; Restore bitmaps start dest byte
  834.     rol   ah,1                        ; Shift mask for next plane
  835.     adc   di,0                        ; If wrapped increment dest address
  836.     dec   [Plane]                     ; Decrement plane counter
  837.     jnz   @@PlaneLoop                 ; Jump if more planes left
  838.  
  839.     pop   ds                          ; restore data segment
  840.     pop   di                          ; restore registers
  841.     pop   si
  842.     ret
  843. xputpbm  endp
  844.  
  845. xflippbm  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word
  846. LOCAL Plane:byte,BMHeight:byte,LineInc:word
  847.     push  si
  848.     push  di
  849.     push  ds
  850.     cld
  851.     mov   ax,SCREENSEG
  852.     mov   es,ax
  853.     mov   ax,[Y]                      ; Calculate dest screen row
  854.     mov   bx,[ScrnLogicalByteWidth]   ;  by mult. dest Y coord by Screen
  855.     mul   bx                          ;  width then adding screen offset
  856.     mov   di,[ScrnOffs]               ;  store result in DI
  857.     add   di,ax
  858.     mov   cx,[X]                      ; Load X coord into CX and make a
  859.     mov   dx,cx                       ;  copy in DX
  860.     shr   dx,2                        ; Find starting byte in dest row
  861.     add   di,dx                       ;  add to DI giving screen offset of
  862.                                                                                     ;  first pixel's byte
  863.     lds   si,[Bitmap]                 ; DS:SI -> Bitmap data
  864.     lodsw                             ; Al = B.M. width (bytes) AH = B.M.
  865.                                                                                     ;  height
  866.     cmp   Orientation,0
  867.     jz    UnFlipped
  868.  
  869.     mov   [BMHeight],ah               ; Save source bitmap dimensions
  870.                 xor   ah,ah                       ; LineInc = bytes to the begin.
  871.     add   bx,ax                       ;  of bitmaps next row on screen
  872.     mov   [LineInc],bx
  873.     mov   bh,al                       ; Use bh as column loop count
  874.                 and   cx,0003h              ; mask X coord giving plane of 1st
  875.                                                                         ; bitmap pixel(zero CH coincidentally)
  876.     mov   ah,11h                      ; Init. mask for VGA plane selection
  877.     shl   ah,cl                       ; Shift for starting pixel plane
  878.     mov   dx,SCINDEX                  ; Prepare VGA for cpu to video writes
  879.     mov   al,MAPMASK
  880.     out   dx,al
  881.     inc   dx
  882.     mov   [Plane],4                   ; Set plane counter to 4
  883. @@PlaneLoop:
  884.     push  di                          ; Save bitmap's start dest. offset
  885.     mov   bl,[BMHeight]               ; Reset row counter (BL)
  886.     mov   al,ah
  887.     out   dx,al                       ; set vga write plane
  888. @@RowLoop:
  889.     mov   cl,bh                       ; Reset Column counter cl
  890. @@ColLoop:
  891.     lodsb
  892.     mov   es:[di],al
  893.     dec   di
  894.     sub   di,2
  895.     loop  @@ColLoop                   ; loop if more columns left
  896. @@DoneCol:
  897.     add   di,[LineInc]                ; Move to next row
  898.     dec   bl                          ; decrement row counter
  899.     jnz   @@RowLoop                   ; Jump if more rows left
  900.     pop   di                          ; Restore bitmaps start dest byte
  901.     ror   ah,1                        ; Shift mask for next plane
  902.     sbb   di,0                        ; If wrapped increment dest address
  903.     dec   [Plane]                     ; Decrement plane counter
  904.     jnz   @@PlaneLoop                 ; Jump if more planes left
  905.     pop   ds                          ; restore data segment
  906.     pop   di                          ; restore registers
  907.     pop   si
  908.     ret
  909.  
  910. xflippbm  endp
  911.  
  912. xgetpbm  proc far X:word,Y:word,SrcWidth:byte,SrcHeight:byte,ScrnOffs:word,Bitmap:dword
  913. LOCAL Plane:byte,LineInc:word
  914.     push  si
  915.     push  di
  916.     push  ds
  917.     cld
  918.  
  919.     mov   ax,[Y]                      ; Calculate screen row
  920.     mov   bx,[ScrnLogicalByteWidth]   ;  by mult. Y coord by Screen
  921.     mul   bx                          ;  width then adding screen offset
  922.     mov   si,[ScrnOffs]               ;  store result in SI
  923.     add   si,ax
  924.     mov   cx,[X]                      ; Load X coord into CX and make a
  925.     mov   dx,cx                       ;  copy in DX
  926.     shr   dx,2                        ; Find starting byte in screen row
  927.     add   si,dx                       ;  add to SI giving screen offset of
  928.                                                                         ;  first pixel's byte
  929.     mov   ax,SCREENSEG
  930.     mov   ds,ax
  931.     les   di,[Bitmap]                 ; ES:DI -> Bitmap data
  932.     mov   al,[SrcWidth]
  933.     mov   ah,[SrcHeight]
  934.     stosw                             ; Al = B.M. width (bytes) AH = B.M.
  935.                                                                         ;  height
  936.     xor   ah,ah                                             ; LineInc = bytes to the begin.
  937.     sub   bx,ax                       ;  of bitmaps next row on screen
  938.     mov   [LineInc],bx
  939.     mov   bh,al
  940.                                                                         ; Self Modifying, Shame, shame shame..
  941.     and   cx,0003h                    ; mask X coord giving plane of 1st
  942.                                                                         ; bitmap pixel(zero CH coincidentally)
  943.     mov   ah,11h                      ; Init. mask for VGA plane selection
  944.     shl   ah,cl                       ; Shift for starting pixel plane
  945.     mov   dx,GCINDEX                  ; Prepare VGA for cpu to video reads
  946.     mov   al,READMAP
  947.     out   dx,al
  948.     inc   dx
  949.     mov   [Plane],4                   ; Set plane counter (BH) to 4
  950.     mov   al,cl
  951. @@PlaneLoop:
  952.     push  si
  953.     mov   bl,[SrcHeight]
  954.     out   dx,al
  955. @@RowLoop:
  956.     mov   cl,bh
  957.     shr   cl,1
  958.     rep   movsw                       ; Copy a complete row for curr plane
  959.     adc   cl,0
  960.     rep   movsb
  961.     add   si,[LineInc]                ; Move to next row
  962.     dec   bl                          ; decrement row counter
  963.     jnz   @@RowLoop                   ; Jump if more rows left
  964.     pop   si                          ; Restore bitmaps start dest byte
  965.  
  966.     inc   al                          ; Select next plane to read from
  967.     and   al,3                        ;
  968.  
  969.     rol   ah,1                        ; Shift mask for next plane
  970.     adc   si,0                        ; If wrapped increment dest address
  971.     dec   [Plane]                     ; Decrement plane counter
  972.     jnz   @@PlaneLoop                 ; Jump if more planes left
  973.  
  974.     pop   ds                          ; restore data segment
  975.     pop   di                          ; restore registers
  976.     pop   si
  977.     ret
  978. xgetpbm  endp
  979.  
  980. xputmaskedpbmclipx  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  981. LOCAL   Plane:byte,CType,LeftSkip,DataInc,AWidth,Height,TopRow,LineInc:word
  982.     push  si
  983.     push  di
  984.     push  ds
  985.     cld
  986.  
  987.     les   si,[Bitmap]                 ; Point ES:SI to start of bitmap
  988.  
  989.     xor   ax,ax                       ; Clear AX
  990.     mov   [CType],ax                  ; Clear Clip type descision var
  991.     mov   al,byte ptr es:[si]         ; AX=width (byte coverted to word)
  992.  
  993.  
  994.     mov   di,[X]                      ; DI = X coordinate of dest
  995.     mov   cx,di                       ; copy to CX
  996.     sar   di,2                        ; convert to offset in row
  997.     mov   dx,[LeftClip]               ; Is X Coord to the right of
  998.     sub   dx,di                       ; LeftClip ?
  999.     jle   @@NotLeftClip               ; Yes! => no left clipping
  1000.     cmp   dx,ax                       ; Is dist of X Coord from
  1001.     jnl   @@NotVisible                ; ClipLeft > Width ? yes => the
  1002.                         ; bitmap is not visible
  1003.     add   di,dx
  1004.     mov   [LeftSkip],dx
  1005.     mov   [DataInc],dx
  1006.     sub   ax,dx
  1007.     mov   [CType],1
  1008.     jmp   short @@HorizClipDone
  1009.  
  1010. @@NotVisible:
  1011.     mov   ax,1
  1012.     pop   ds                          ; restore data segment
  1013.     pop   di
  1014.     pop   si
  1015.     ret
  1016.  
  1017. @@NotLeftClip:
  1018.     mov   dx,[RightClip]
  1019.     sub   dx,di
  1020.     js    @@NotVisible
  1021.     mov   [LeftSkip],0
  1022.     mov   [DataInc],0
  1023.     cmp   dx,ax
  1024.     jge   @@HorizClipDone
  1025.     inc   dx
  1026.     sub   ax,dx
  1027.     mov   [DataInc],ax
  1028.     mov   ax,dx
  1029.     mov   [CType],-1
  1030.  
  1031. @@HorizClipDone:
  1032.  
  1033.     xor   bh,bh
  1034.     mov   bl,byte ptr es:[si+1]
  1035.  
  1036.     mov   [AWidth],ax
  1037.     mov   [Height],bx
  1038.  
  1039.  
  1040.     add   si,2
  1041.     add   si,[LeftSkip]
  1042.     mov   bx,[ScrnLogicalByteWidth]
  1043.     mov   dx,bx
  1044.     sub   dx,ax
  1045.     mov   [LineInc],dx
  1046.  
  1047.     mov   ax,[Y]
  1048.     mul   bx
  1049.     add   di,ax
  1050.     add   di,[ScrnOffs]
  1051.  
  1052.     mov   ax,es                       ; copy ES to DS
  1053.     mov   dx,SCREENSEG                ; Point ES to VGA segment
  1054.     mov   ds,ax
  1055.     mov   es,dx
  1056.  
  1057.     and   cx,3
  1058.     mov   ah,11h
  1059.     shl   ah,cl
  1060.  
  1061.     mov   dx,SCINDEX
  1062.     mov   al,MAPMASK
  1063.     out   dx,al
  1064.     inc   dx
  1065.     mov   [Plane],4
  1066.     mov   bh,byte ptr [AWidth]
  1067. @@PlaneLoop:
  1068.     push  di
  1069.     mov   bl,byte ptr [Height]
  1070.     mov   al,ah
  1071.     out   dx,al
  1072. @@RowLoop:
  1073.     mov   cl,bh
  1074.     jcxz  @@NoWidth
  1075. @@ColLoop:
  1076.     lodsb
  1077.     or    al,al
  1078.     jz    @@NoPixel
  1079.     mov   es:[di],al
  1080. @@NoPixel:
  1081.     inc   di
  1082.     loop @@ColLoop
  1083. @@NoWidth:
  1084.     add   si,[DataInc]
  1085.     add   di,[LineInc]
  1086.     dec   bl
  1087.     jnz   @@RowLoop
  1088.     pop   di
  1089.     rol   ah,1
  1090.  
  1091.     jnb   @@Nocarry                   ; Jump if not plane transition
  1092.     mov   bl,ah                       ; Save Plane Mask
  1093.     mov   ax,[CType]                  ; set AX to clip type inc variable
  1094.     add   bh,al                       ; Update advancing variables
  1095.     sub   [DataInc],ax                ;
  1096.     sub   [LineInc],ax                ;
  1097.     cmp   al,0                        ; What type of clip do we have
  1098.     mov   ah,bl                       ;   restore Plane mask
  1099.     jg    @@RightAdvance              ; jump on a right clip!
  1100.     inc   di                          ; otherwise increment DI
  1101.     jmp   @@Nocarry
  1102. @@RightAdvance:
  1103.     dec si
  1104. @@Nocarry:
  1105.     dec   [Plane]                     ; Decrement plane counter
  1106.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1107.  
  1108.     xor   ax,ax
  1109.     pop   ds                          ; restore data segment
  1110.     pop   di                          ; restore registers
  1111.     pop   si
  1112.     ret
  1113. xputmaskedpbmclipx  endp
  1114.  
  1115. xputmaskedpbmclipy  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  1116. LOCAL   AWidth,Height,TopRow,LineInc,PlaneInc:word
  1117.     push  si
  1118.     push  di
  1119.     push  ds
  1120.     cld
  1121.  
  1122.     les   si,[Bitmap]
  1123.  
  1124.     xor   bh,bh
  1125.     mov   bl,byte ptr es:[si+1]       ; BX = height
  1126.  
  1127.     xor   ah,ah
  1128.     mov   al,byte ptr es:[si]         ; AX = width
  1129.  
  1130.     mov   cx,ax                       ; Save AX
  1131.     mul   bx                          ; AX = AX*BX = bytes/plane
  1132.     mov   [PlaneInc],ax               ;  save as PlaneInc
  1133.     mov   ax,cx                       ; Restore AX
  1134.  
  1135.     mov   di,[X]
  1136.     mov   cx,di
  1137.     shr   di,2
  1138.  
  1139.     ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  1140.  
  1141.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  1142.     sub   dx,[Y]                  ; clipping border
  1143.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  1144.     cmp   dx,bx
  1145.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  1146.     mov   [TopRow],dx
  1147.     sub   bx,dx
  1148.     add   [Y],dx
  1149.     jmp   short @@VertClipDone
  1150.  
  1151.     ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  1152.  
  1153. @@NotVisible:
  1154.     mov   ax,1
  1155.     pop   ds                          ; restore data segment
  1156.     pop   di                          ; restore registers
  1157.     pop   si
  1158.     ret
  1159.  
  1160.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1161.  
  1162. @@NotTopClip:
  1163.     mov   dx,[BottomClip]
  1164.     sub   dx,[Y]
  1165.     js    @@NotVisible
  1166.     mov   [TopRow],0
  1167.     cmp   dx,bx
  1168.     jg    @@VertClipDone
  1169.     inc   dx
  1170.     mov   bx,dx
  1171.  
  1172. @@VertClipDone:
  1173.  
  1174.     mov   [AWidth],ax
  1175.     mov   [Height],bx                 ; Calculate relative offset in data
  1176.     mul   [TopRow]                    ;  of first visible scanline
  1177.     add   ax,2                        ; Skip dimension bytes in source
  1178.     add   si,ax                       ; Skip top rows that arent visible
  1179.  
  1180.  
  1181.     mov   ax,[Y]                      ; Calculate screen row
  1182.     mov   bx,[ScrnLogicalByteWidth]  ;  by mult. Y coord by Screen
  1183.     mul   bx                          ;  width then adding screen offset
  1184.     add   di,ax
  1185.     add   di,[ScrnOffs]
  1186.     sub   bx,[AWidth]                  ; calculate difference from end of
  1187.     mov   [LineInc],bx                ; b.m. in curr line to beginning of
  1188.                         ; b.m. on next scan line
  1189.  
  1190.     mov   ax,es                       ; copy ES to DS
  1191.     mov   dx,SCREENSEG                ; Point ES to VGA segment
  1192.     mov   ds,ax
  1193.     mov   es,dx
  1194.  
  1195.     mov   ah,11h                      ; Set up initial plane mask
  1196.     and   cx,3
  1197.     shl   ah,cl
  1198.  
  1199.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  1200.     mov   al,MAPMASK
  1201.     out   dx,al
  1202.     inc   dx
  1203.     mov   bh,4                        ; Set plane counter to 4
  1204. @@PlaneLoop:
  1205.     push  di        ; Save bitmap's start dest. offset
  1206.     push  si                          ; Save Bitmaps data offset
  1207.     mov   bl,byte ptr [Height]        ; Reset row counter (BL)
  1208.     mov   al,ah
  1209.     out   dx,al                       ; set vga write plane
  1210. @@RowLoop:
  1211.     mov   cl,byte ptr [AWidth]         ; Reset Column counter cl
  1212. @@ColLoop:
  1213.     lodsb                             ; Get next source bitmap byte
  1214.     or    al,al                       ; If not zero then write to dest.
  1215.     jz    @@NoPixel                   ; otherwise skip to next byte
  1216.     mov   es:[di],al
  1217. @@NoPixel:
  1218.     inc   di
  1219.     loop  @@ColLoop                   ; loop if more columns left
  1220.     add   di,[LineInc]                ; Move to next row
  1221.     dec   bl                          ; decrement row counter
  1222.     jnz   @@RowLoop                   ; Jump if more rows left
  1223.     pop   si                          ; Restore SI and set to offset of
  1224.     add   si,[PlaneInc]               ; first vis pixel in next plane data
  1225.     pop   di                          ; Restore bitmaps start dest byte
  1226.     rol   ah,1                        ; Shift mask for next plane
  1227.     adc   di,0                        ; if carry increment screen offset
  1228.     dec   bh                          ; Decrement plane counter
  1229.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1230.  
  1231.     xor   ax,ax
  1232.     pop   ds                          ; restore data segment
  1233.     pop   di                          ; restore registers
  1234.     pop   si
  1235.     ret
  1236. xputmaskedpbmclipy   endp
  1237.  
  1238. xputmaskedpbmclipxy  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  1239. LOCAL   Plane:byte,CType,LeftSkip,DataInc,AWidth,Height,TopRow,LineInc,PlaneInc:word
  1240.     push  si
  1241.     push  di
  1242.     push  ds
  1243.     cld
  1244.  
  1245.     les   si,[Bitmap]
  1246.  
  1247.     xor   ax,ax
  1248.     mov   [CType],ax
  1249.     mov   al,byte ptr es:[si]         ; AX = width
  1250.     xor   bh,bh
  1251.     mov   bl,byte ptr es:[si+1]       ; BX = height
  1252.  
  1253.     mov   cx,ax                       ; Save AX
  1254.     mul   bx                          ; AX = AX*BX = bytes/plane
  1255.     mov   [PlaneInc],ax               ;  save as PlaneInc
  1256.     mov   ax,cx                       ; Restore AX
  1257.  
  1258.  
  1259.     mov   di,[X]                      ; DI = X coordinate of dest.
  1260.     mov   cx,di                       ; save in CX
  1261.     sar   di,2                        ; convert to address byte
  1262.  
  1263.  
  1264.         ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  1265.  
  1266.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  1267.     sub   dx,[Y]                  ; clipping border
  1268.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  1269.     cmp   dx,bx
  1270.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  1271.     mov   [TopRow],dx
  1272.     sub   bx,dx
  1273.     add   [Y],dx
  1274.     jmp   short @@VertClipDone
  1275.  
  1276.     ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  1277.  
  1278. @@NotVisible:
  1279.     mov   ax,1
  1280.     pop   ds                          ; restore data segment
  1281.     pop   di                          ; restore registers
  1282.     pop   si
  1283.     ret
  1284.  
  1285.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1286.  
  1287. @@NotTopClip:
  1288.     mov   dx,[BottomClip]
  1289.     sub   dx,[Y]
  1290.     js    @@NotVisible
  1291.     mov   [TopRow],0
  1292.     cmp   dx,bx
  1293.     jg    @@VertClipDone
  1294.     inc   dx
  1295.     mov   bx,dx
  1296.  
  1297. @@VertClipDone:
  1298.  
  1299.     ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1300.  
  1301.     mov   dx,[LeftClip]
  1302.     sub   dx,di
  1303.     jle   @@NotLeftClip
  1304.     cmp   dx,ax
  1305.     jnl   @@NotVisible
  1306.  
  1307.     add   di,dx
  1308.     mov   [LeftSkip],dx
  1309.     mov   [DataInc],dx
  1310.     sub   ax,dx
  1311.     mov   [CType],1
  1312.     jmp   short @@HorizClipDone
  1313.  
  1314.     ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1315.  
  1316. @@NotLeftClip:
  1317.     mov   dx,[RightClip]
  1318.     sub   dx,di
  1319.     js    @@NotVisible
  1320.     mov   [LeftSkip],0
  1321.     mov   [DataInc],0
  1322.     cmp   dx,ax
  1323.                 jge   @@HorizClipDone       ; was jg
  1324.     inc   dx
  1325.     sub   ax,dx
  1326.     mov   [DataInc],ax
  1327.     mov   ax,dx
  1328.  
  1329.  
  1330.     mov   [CType],-1
  1331.  
  1332. @@HorizClipDone:
  1333.  
  1334.  
  1335.  
  1336.     mov   [AWidth],ax                  ; Save width and height of clipped
  1337.     mov   [Height],bx                 ;  image
  1338.  
  1339.     add   ax,[DataInc]                ; AX = original width of image
  1340.     mul   [TopRow]                    ; Calculate bytes in clipped top
  1341.     add   si,ax             ;  rows
  1342.     add   si,2                        ; Skip dimension bytes in source
  1343.     add   si,[LeftSkip]               ; Skip pixels in front of row that
  1344.                         ;  are clipped
  1345.  
  1346.     mov   bx,[ScrnLogicalByteWidth]  ; Set BX to Logical Screen Width
  1347.     mov   dx,bx                       ; BX - Width of image = No. bytes
  1348.     sub   dx,[AWidth]                  ;  to first byte of next screen
  1349.     mov   [LineInc],dx                ;  row.
  1350.  
  1351.     mov   ax,[Y]                      ; Calculate screen start row
  1352.     mul   bx                          ;  then adding screen offset
  1353.     add   di,ax
  1354.     add   di,[ScrnOffs]
  1355.  
  1356.     mov   ax,es                       ; copy ES to DS
  1357.     mov   dx,SCREENSEG                ; Point ES to VGA segment
  1358.     mov   ds,ax
  1359.     mov   es,dx
  1360.  
  1361.     and   cx,3
  1362.     mov   ah,11h                      ; Set up initial plane mask
  1363.     shl   ah,cl
  1364.  
  1365.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  1366.     mov   al,MAPMASK
  1367.     out   dx,al
  1368.     inc   dx
  1369.     mov   [Plane],4                   ; Set plane counter to 4
  1370.     mov   bh,byte ptr [AWidth]         ; set bh to width for fast looping
  1371. @@PlaneLoop:
  1372.     push  di        ; Save bitmap's start dest. offset
  1373.     push  si
  1374.     mov   bl,byte ptr [Height]        ; Reset row counter (BL)
  1375.     mov   al,ah
  1376.     out   dx,al                       ; set vga write plane
  1377. @@RowLoop:
  1378.     mov   cl,bh                       ; Reset Column counter cl
  1379.     jcxz   @@NoWidth
  1380. @@ColLoop:
  1381.     lodsb                     ; Get next source bitmap byte
  1382.     or    al,al                       ; If not zero then write to dest.
  1383.     jz    @@NoPixel                   ; otherwise skip to next byte
  1384.     mov   es:[di],al
  1385. @@NoPixel:
  1386.     inc   di
  1387.     loop @@ColLoop
  1388. @@NoWidth:
  1389.     add   si,[DataInc]                ; Move to next source row
  1390.     add   di,[LineInc]                ; Move to next screen row
  1391.     dec   bl                          ; decrement row counter
  1392.     jnz   @@RowLoop                   ; Jump if more rows left
  1393.     pop   si                          ; Restore SI and set to offset of
  1394.     add   si,[PlaneInc]               ; first vis pixel in next plane data
  1395.     pop   di                          ; Restore bitmaps start dest byte
  1396.     rol   ah,1              ; Shift mask for next plane
  1397.  
  1398.     ; Plane Transition (A HACK but it works!)
  1399.  
  1400.     jnb   @@Nocarry                   ; Jump if not plane transition
  1401.     mov   bl,ah                       ; Save Plane Mask
  1402.     mov   ax,[CType]                  ; set AX to clip type inc variable
  1403.     add   bh,al                       ; Update advancing variables
  1404.     sub   [DataInc],ax                ;
  1405.     sub   [LineInc],ax                ;
  1406.     cmp   al,0                        ; What type of clip do we have
  1407.     mov   ah,bl                       ;   restore Plane mask
  1408.     jg    @@RightAdvance              ; jump on a right clip!
  1409.     inc   di                          ; otherwise increment DI
  1410.     jmp   @@Nocarry
  1411. @@RightAdvance:
  1412.     dec   si
  1413. @@Nocarry:
  1414.     dec   [Plane]                     ; Decrement plane counter
  1415.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1416.  
  1417.     xor   ax,ax
  1418.     pop   ds                          ; restore data segment
  1419.     pop   di                          ; restore registers
  1420.     pop   si
  1421.     ret
  1422. xputmaskedpbmclipxy  endp
  1423.  
  1424. xputpbmclipx  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  1425. LOCAL   Plane:byte,CType,LeftSkip,DataInc,AWidth,Height,TopRow,LineInc:word
  1426.     push  si
  1427.     push  di
  1428.     push  ds
  1429.     cld
  1430.  
  1431.     les   si,[Bitmap]
  1432.  
  1433.     xor   ax,ax
  1434.     mov   [CType],ax
  1435.     mov   al,byte ptr es:[si]         ; AX = width
  1436.  
  1437.  
  1438.     mov   di,[X]                      ; DI = X coordinate of dest.
  1439.     mov   cx,di                       ; save in CX
  1440.     sar   di,2                        ; convert to address byte
  1441.  
  1442.  
  1443.  
  1444.     ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1445.  
  1446.     mov   dx,[LeftClip]
  1447.     sub   dx,di
  1448.     jle   @@NotLeftClip
  1449.     cmp   dx,ax
  1450.     jnl   @@NotVisible
  1451.  
  1452.     add   di,dx
  1453.     mov   [LeftSkip],dx
  1454.     mov   [DataInc],dx
  1455.     sub   ax,dx
  1456.     mov   [CType],1
  1457.     jmp   short @@HorizClipDone
  1458.  
  1459.     ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  1460.  
  1461. @@NotVisible:
  1462.     mov   ax,1
  1463.     pop   ds                          ; restore data segment
  1464.     pop   di                          ; restore registers
  1465.     pop   si
  1466.     ret
  1467.  
  1468.     ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1469.  
  1470. @@NotLeftClip:
  1471.     mov   dx,[RightClip]
  1472.     sub   dx,di
  1473.     js    @@NotVisible
  1474.     mov   [LeftSkip],0
  1475.     mov   [DataInc],0
  1476.     cmp   dx,ax
  1477.                 jge   @@HorizClipDone       ; was jg
  1478.     inc   dx
  1479.     sub   ax,dx
  1480.     mov   [DataInc],ax
  1481.     mov   ax,dx
  1482.     mov   [CType],-1
  1483.  
  1484. @@HorizClipDone:
  1485.  
  1486.     xor   bh,bh
  1487.     mov   bl,byte ptr es:[si+1]       ; BX = height
  1488.  
  1489.     mov   [AWidth],ax                  ; Save width and height of clipped
  1490.     mov   [Height],bx                 ;  image
  1491.  
  1492.  
  1493.     add   si,2                        ; Skip dimension bytes in source
  1494.     add   si,[LeftSkip]               ; Skip pixels in front of row that
  1495.                         ;  are clipped
  1496.  
  1497.  
  1498.     mov   bx,[ScrnLogicalByteWidth]  ; Set BX to Logical Screen Width
  1499.     mov   dx,bx                       ; BX - Width of image = No. bytes
  1500.     sub   dx,ax                       ;  to first byte of next screen
  1501.     mov   [LineInc],dx                ;  row.
  1502.  
  1503.     mov   ax,[Y]                      ; Calculate screen start row
  1504.     mul   bx                          ;  then adding screen offset
  1505.     add   di,ax
  1506.     add   di,[ScrnOffs]
  1507.  
  1508.     mov   ax,es                       ; copy ES to DS
  1509.     mov   dx,SCREENSEG                ; Point ES to VGA segment
  1510.     mov   ds,ax
  1511.     mov   es,dx
  1512.  
  1513.     and   cx,3
  1514.     mov   ah,11h                      ; Set up initial plane mask
  1515.     shl   ah,cl
  1516.  
  1517.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  1518.     mov   al,MAPMASK
  1519.     out   dx,al
  1520.     inc   dx
  1521.     mov   [Plane],4                   ; Set plane counter to 4
  1522.     mov   bh,byte ptr [AWidth]         ; set bh to width for fast looping
  1523. @@PlaneLoop:
  1524.     push  di        ; Save bitmap's start dest. offset
  1525.     mov   bl,byte ptr [Height]        ; Reset row counter (BL)
  1526.     mov   al,ah
  1527.     out   dx,al                       ; set vga write plane
  1528. @@RowLoop:
  1529.     mov   cl,bh                       ; Reset Column counter cl
  1530.     shr   cl,1
  1531.     rep   movsw                       ; Copy a complete row
  1532.     adc   cl,0
  1533.     rep   movsb
  1534.     add   si,[DataInc]                ; Move to next source row
  1535.     add   di,[LineInc]                ; Move to next screen row
  1536.     dec   bl                          ; decrement row counter
  1537.     jnz   @@RowLoop                   ; Jump if more rows left
  1538.     pop   di                          ; Restore bitmaps start dest byte
  1539.     rol   ah,1              ; Shift mask for next plane
  1540.  
  1541.     ; Plane Transition (A HACK but it works!)
  1542.  
  1543.     jnb   @@Nocarry                   ; Jump if not plane transition
  1544.     mov   bl,ah                       ; Save Plane Mask
  1545.     mov   ax,[CType]                  ; set AX to clip type inc variable
  1546.     add   bh,al                       ; Update advancing variables
  1547.     sub   [DataInc],ax                ;
  1548.     sub   [LineInc],ax                ;
  1549.     cmp   al,0                        ; What type of clip do we have
  1550.     mov   ah,bl                       ;   restore Plane mask
  1551.     jg    @@RightAdvance              ; jump on a right clip!
  1552.     inc   di                          ; otherwise increment DI
  1553.     jmp   @@Nocarry
  1554. @@RightAdvance:
  1555.     dec si
  1556. @@Nocarry:
  1557.     dec   [Plane]                     ; Decrement plane counter
  1558.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1559.  
  1560.     xor   ax,ax
  1561.     pop   ds                          ; restore data segment
  1562.     pop   di                          ; restore registers
  1563.     pop   si
  1564.     ret
  1565. xputpbmclipx  endp
  1566.  
  1567. xputpbmclipy  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  1568. LOCAL   AWidth,Height,TopRow,LineInc,PlaneInc:word
  1569.     push  si
  1570.     push  di
  1571.     push  ds
  1572.     cld
  1573.  
  1574.     les   si,[Bitmap]
  1575.  
  1576.     xor   bh,bh
  1577.     mov   bl,byte ptr es:[si+1]   ; BX = height
  1578.     ;mov   [Height],bx
  1579.  
  1580.     xor   ah,ah
  1581.     mov   al,byte ptr es:[si]     ; AX = width
  1582.     mov   [AWidth],ax
  1583.  
  1584.     mov   cx,ax                       ; Save AX
  1585.     mul   bx                          ; AX = AX*BX = bytes/plane
  1586.     mov   [PlaneInc],ax               ;  save as PlaneInc
  1587.     mov   ax,cx                       ; Restore AX
  1588.  
  1589.     mov   di,[X]
  1590.     mov   cx,di
  1591.     and   cx,3
  1592.     shr   di,2
  1593.  
  1594.     ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  1595.  
  1596.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  1597.     sub   dx,[Y]                  ; clipping border
  1598.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  1599.     cmp   dx,bx
  1600.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  1601.     mov   [TopRow],dx
  1602.     sub   bx,dx
  1603.     add   [Y],dx
  1604.     jmp   short @@VertClipDone
  1605.  
  1606.     ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  1607.  
  1608. @@NotVisible:
  1609.     mov   ax,1
  1610.     pop   ds                          ; restore data segment
  1611.     pop   di                          ; restore registers
  1612.     pop   si
  1613.     ret
  1614.  
  1615.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1616.  
  1617. @@NotTopClip:
  1618.     mov   dx,[BottomClip]
  1619.     sub   dx,[Y]
  1620.     js    @@NotVisible
  1621.     mov   [TopRow],0
  1622.     cmp   dx,bx
  1623.     jg    @@VertClipDone
  1624.     inc   dx
  1625.     mov   bx,dx
  1626.  
  1627. @@VertClipDone:
  1628.  
  1629.     mov   [Height],bx                 ; Calculate relative offset in data
  1630.     mul   [TopRow]                    ;  of first visible scanline
  1631.     add   ax,2                        ; Skip dimension bytes in source
  1632.     add   si,ax                       ; Skip top rows that arent visible
  1633.  
  1634.  
  1635.     mov   ax,[Y]                      ; Calculate screen row
  1636.     mov   bx,[ScrnLogicalByteWidth]  ;  by mult. Y coord by Screen
  1637.     mul   bx                          ;  width then adding screen offset
  1638.     add   di,ax
  1639.     add   di,[ScrnOffs]
  1640.     sub   bx,[AWidth]                  ; calculate difference from end of
  1641.     mov   [LineInc],bx                ; b.m. in curr line to beginning of
  1642.                         ; b.m. on next scan line
  1643.  
  1644.     mov   ax,es                       ; copy ES to DS
  1645.     mov   dx,SCREENSEG                ; Point ES to VGA segment
  1646.     mov   ds,ax
  1647.     mov   es,dx
  1648.  
  1649.     mov   ah,11h                      ; Set up initial plane mask
  1650.     shl   ah,cl
  1651.  
  1652.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  1653.     mov   al,MAPMASK
  1654.     out   dx,al
  1655.     inc   dx
  1656.     mov   bh,4                        ; Set plane counter to 4
  1657. @@PlaneLoop:
  1658.     push  di        ; Save bitmap's start dest. offset
  1659.     push  si                          ; Save Bitmaps data offset
  1660.     mov   bl,byte ptr [Height]        ; Reset row counter (BL)
  1661.     mov   al,ah
  1662.     out   dx,al                       ; set vga write plane
  1663. @@RowLoop:
  1664.     mov   cl,byte ptr [AWidth]         ; Reset Column counter cl
  1665.     shr   cl,1
  1666.     rep   movsw                       ; Copy a complete row
  1667.     adc   cl,0
  1668.     rep   movsb
  1669.  
  1670.     add   di,[LineInc]                ; Move to next row
  1671.     dec   bl                          ; decrement row counter
  1672.     jnz   @@RowLoop                   ; Jump if more rows left
  1673.     pop   si                          ; Restore SI and set to offset of
  1674.     add   si,[PlaneInc]               ; first vis pixel in next plane data
  1675.     pop   di                          ; Restore bitmaps start dest byte
  1676.     rol   ah,1                        ; Shift mask for next plane
  1677.     adc   di,0                        ; if carry increment screen offset
  1678.     dec   bh                          ; Decrement plane counter
  1679.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1680.  
  1681.     xor   ax,ax
  1682.     pop   ds                          ; restore data segment
  1683.     pop   di                          ; restore registers
  1684.     pop   si
  1685.     ret
  1686. xputpbmclipy   endp
  1687.  
  1688.  
  1689. xputpbmclipxy  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  1690. LOCAL   Plane:byte,CType,LeftSkip,DataInc,AWidth,Height,TopRow,LineInc,PlaneInc:word
  1691.     push  si
  1692.     push  di
  1693.     push  ds
  1694.     cld
  1695.  
  1696.     les   si,[Bitmap]
  1697.  
  1698.     xor   ax,ax
  1699.     mov   [CType],ax
  1700.     mov   al,byte ptr es:[si]         ; AX = width
  1701.     xor   bh,bh
  1702.     mov   bl,byte ptr es:[si+1]       ; BX = height
  1703.  
  1704.     mov   cx,ax                       ; Save AX
  1705.     mul   bx                          ; AX = AX*BX = bytes/plane
  1706.     mov   [PlaneInc],ax               ;  save as PlaneInc
  1707.     mov   ax,cx                       ; Restore AX
  1708.  
  1709.  
  1710.     mov   di,[X]                      ; DI = X coordinate of dest.
  1711.     mov   cx,di                       ; save in CX
  1712.     sar   di,2                        ; convert to address byte
  1713.  
  1714.  
  1715.         ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  1716.  
  1717.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  1718.     sub   dx,[Y]                  ; clipping border
  1719.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  1720.     cmp   dx,bx
  1721.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  1722.     mov   [TopRow],dx
  1723.     sub   bx,dx
  1724.     add   [Y],dx
  1725.     jmp   short @@VertClipDone
  1726.  
  1727.     ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  1728.  
  1729. @@NotVisible:
  1730.     mov   ax,1
  1731.     pop   ds                          ; restore data segment
  1732.     pop   di                          ; restore registers
  1733.     pop   si
  1734.     ret
  1735.  
  1736.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1737.  
  1738. @@NotTopClip:
  1739.     mov   dx,[BottomClip]
  1740.     sub   dx,[Y]
  1741.     js    @@NotVisible
  1742.     mov   [TopRow],0
  1743.     cmp   dx,bx
  1744.     jg    @@VertClipDone
  1745.     inc   dx
  1746.     mov   bx,dx
  1747.  
  1748. @@VertClipDone:
  1749.  
  1750.     ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1751.  
  1752.     mov   dx,[LeftClip]
  1753.     sub   dx,di
  1754.     jle   @@NotLeftClip
  1755.     cmp   dx,ax
  1756.     jnl   @@NotVisible
  1757.  
  1758.     add   di,dx
  1759.     mov   [LeftSkip],dx
  1760.     mov   [DataInc],dx
  1761.     sub   ax,dx
  1762.     mov   [CType],1
  1763.     jmp   short @@HorizClipDone
  1764.  
  1765.     ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1766.  
  1767. @@NotLeftClip:
  1768.     mov   dx,[RightClip]
  1769.     sub   dx,di
  1770.     js    @@NotVisible
  1771.     mov   [LeftSkip],0
  1772.     mov   [DataInc],0
  1773.     cmp   dx,ax
  1774.                 jge   @@HorizClipDone       ; was jg
  1775.     inc   dx
  1776.     sub   ax,dx
  1777.     mov   [DataInc],ax
  1778.     mov   ax,dx
  1779.     mov   [CType],-1
  1780.  
  1781. @@HorizClipDone:
  1782.  
  1783.  
  1784.  
  1785.     mov   [AWidth],ax                  ; Save width and height of clipped
  1786.     mov   [Height],bx                 ;  image
  1787.  
  1788.     add   ax,[DataInc]                ; AX = original width of image
  1789.     mul   [TopRow]                    ; Calculate bytes in clipped top
  1790.     add   si,ax             ;  rows
  1791.     add   si,2                        ; Skip dimension bytes in source
  1792.     add   si,[LeftSkip]               ; Skip pixels in front of row that
  1793.                         ;  are clipped
  1794.  
  1795.     mov   bx,[ScrnLogicalByteWidth]  ; Set BX to Logical Screen Width
  1796.     mov   dx,bx                       ; BX - Width of image = No. bytes
  1797.     sub   dx,[AWidth]                  ;  to first byte of next screen
  1798.     mov   [LineInc],dx                ;  row.
  1799.  
  1800.     mov   ax,[Y]                      ; Calculate screen start row
  1801.     mul   bx                          ;  then adding screen offset
  1802.     add   di,ax
  1803.     add   di,[ScrnOffs]
  1804.  
  1805.     mov   ax,es                       ; copy ES to DS
  1806.     mov   dx,SCREENSEG                ; Point ES to VGA segment
  1807.     mov   ds,ax
  1808.     mov   es,dx
  1809.  
  1810.  
  1811.  
  1812.     and   cx,3
  1813.     mov   ah,11h                      ; Set up initial plane mask
  1814.     shl   ah,cl
  1815.  
  1816.     mov   dx,SCINDEX                  ; Prepare VGA for cpu to video writes
  1817.     mov   al,MAPMASK
  1818.     out   dx,al
  1819.     inc   dx
  1820.     mov   [Plane],4                   ; Set plane counter to 4
  1821.     mov   bh,byte ptr [AWidth]        ; set bh to width for fast looping
  1822. @@PlaneLoop:
  1823.     push  di        ; Save bitmap's start dest. offset
  1824.     push  si
  1825.     mov   bl,byte ptr [Height]        ; Reset row counter (BL)
  1826.     mov   al,ah
  1827.     out   dx,al                       ; set vga write plane
  1828. @@RowLoop:
  1829.     mov   cl,bh                       ; Reset Column counter cl
  1830.     shr   cl,1
  1831.     rep   movsw                       ; Copy a complete row
  1832.     adc   cl,0
  1833.     rep   movsb
  1834.     add   si,[DataInc]                ; Move to next source row
  1835.     add   di,[LineInc]                ; Move to next screen row
  1836.     dec   bl                          ; decrement row counter
  1837.     jnz   @@RowLoop                   ; Jump if more rows left
  1838.     pop   si                          ; Restore SI and set to offset of
  1839.     add   si,[PlaneInc]               ; first vis pixel in next plane data
  1840.     pop   di                          ; Restore bitmaps start dest byte
  1841.     rol   ah,1              ; Shift mask for next plane
  1842.  
  1843.     ; Plane Transition (A HACK but it works!)
  1844.  
  1845.     jnb   @@Nocarry                   ; Jump if not plane transition
  1846.     mov   bl,ah                       ; Save Plane Mask
  1847.     mov   ax,[CType]                  ; set AX to clip type inc variable
  1848.     add   bh,al                       ; Update advancing variables
  1849.     sub   [DataInc],ax                ;
  1850.     sub   [LineInc],ax                ;
  1851.     cmp   al,0                        ; What type of clip do we have
  1852.     mov   ah,bl                       ;   restore Plane mask
  1853.     jg    @@RightAdvance              ; jump on a right clip!
  1854.     inc   di                          ; otherwise increment DI
  1855.     jmp   @@Nocarry
  1856. @@RightAdvance:
  1857.     dec si
  1858. @@Nocarry:
  1859.     dec   [Plane]                     ; Decrement plane counter
  1860.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1861.  
  1862.     xor   ax,ax
  1863.     pop   ds                          ; restore data segment
  1864.     pop   di                          ; restore registers
  1865.     pop   si
  1866.     ret
  1867. xputpbmclipxy  endp
  1868.  
  1869. xstorevbmimage  proc far VramOffs:word,AAlign:word,LBitmap:dword
  1870. LOCAL BMWidth:byte
  1871.  
  1872.     push  si
  1873.     push  di
  1874.     push  ds
  1875.     cld
  1876.  
  1877.     mov   ax,SCREENSEG               ; Point ES to screen segment
  1878.     mov   es,ax
  1879.     mov   di,[VramOffs]               ; Point ES:DI to VRAM dest start
  1880.     mov   bx,[AAlign]                  ; Set BL to first pixel plane align
  1881.                 and   bl,03h
  1882.  
  1883.     lds   si,[LBitmap]                ; DS:SI -> source linear Bitmap
  1884.                 lodsw                             ; Al = B.M. width (bytes) AH = B.M.
  1885.     mov   bh,ah                       ; Save source bitmap dimensions
  1886.     mov   [BMWidth],al                ;
  1887.  
  1888.     mov   dx,SCINDEX                 ; Initialize Map Mask for plane
  1889.     mov   al,MAPMASK                 ; selection
  1890.                 out   dx,al
  1891.     inc   dx
  1892.     xor   ch,ch                       ; clear CH
  1893. @@RowLoop:
  1894.     mov   cl,bl                       ; Set initial plane for current
  1895.     mov   ah,11h                      ; allignment
  1896.     shl   ah,cl
  1897.  
  1898.     mov   cl,[BMWidth]                ; Initialize column counter
  1899. @@ColLoop:
  1900.     mov   al,ah
  1901.     out   dx,al                       ; set vga write plane
  1902.     lodsb                             ; load next LBM pixel
  1903.     mov   es:[di],al                  ; store it in Video Ram
  1904.     shl   ah,1                        ; rotate plane mask
  1905.     jnb   @@NoAddrIncr                ; Time to increment dest address ?
  1906.     inc   di                          ; Yes: increment addr and reset
  1907.     mov   ah,11h                      ;  plane mask to plane 0
  1908. @@NoAddrIncr:
  1909.     loop  @@ColLoop                   ; Loop to next pixel column
  1910.     cmp   ah,11h
  1911. ; je    @@skip
  1912.     inc   di          ; Increment dest addr
  1913. ;@@skip:
  1914.     dec   bh                          ; Decrement row counter
  1915.     jnz   @@RowLoop                   ; Jump if more rows to go
  1916.     mov   ax,di                       ; calculate video RAM consumed and
  1917.     sub   ax,[VramOffs]               ;   return value
  1918.  
  1919.     pop   ds                          ; restore data segment
  1920.     pop   di                          ; restore registers
  1921.     pop   si
  1922.     ret
  1923. xstorevbmimage  endp
  1924.  
  1925.  
  1926. xputmaskedvbm  proc far X:word,Y:word,ScrnOffs:word,SrcVBM:dword
  1927. LOCAL VBMWidth:word,VBMHeight:word,NextLineIncr:word
  1928.     push  si
  1929.     push  di
  1930.     push  ds
  1931.     cld
  1932.  
  1933.     mov   ax,SCREENSEG               ; Point es to VGA segment
  1934.     mov   es,ax
  1935.     mov   ax,[Y]                      ; Calculate dest screen row
  1936.     mov   cx,[ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen
  1937.     mul   cx                          ;  width then adding screen offset
  1938.  
  1939.     mov   di,[ScrnOffs]               ;  store result in DI
  1940.     add   di,ax
  1941.     mov   si,[X]                      ; Load X coord into CX and make a
  1942.     mov   bx,si                       ;  copy in DX
  1943.     shr   bx,2                        ; Find starting byte in dest row
  1944.     add   di,bx                       ;  add to DI giving screen offset of
  1945.                                                                                     ;  first pixel's byte
  1946.  
  1947.     and   si,3                        ; get pixel alignment in si
  1948.  
  1949.     lds   bx,[SrcVBM]                 ; DS:BX -> VBM data structure
  1950.     shl   si,2                        ; si = offset of data  for curr
  1951.                         ; alignment
  1952.  
  1953.     mov ax,word ptr [bx+ImageHeight]  ; Get image height
  1954.     mov   [VBMHeight],ax
  1955.     mov ax,word ptr [bx+ImageWidth]   ; Get image width
  1956.     mov   [VBMWidth],ax
  1957.  
  1958.     sub   cx,ax                       ; NextLineIncr = bytes to the begin.
  1959.     mov   [NextLineIncr],cx           ;  of bitmaps next row on screen
  1960.     mov   dx,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data
  1961.     mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
  1962.     mov   si,dx
  1963.  
  1964.     mov   dx,GCINDEX                 ; Set bit mask for all bits from
  1965.     mov   ax,BITMASK                 ; VGA latches and none from CPU
  1966.     out   dx,ax
  1967.  
  1968.     mov   dx,SCINDEX                 ; Point SC register to map mask
  1969.     mov   al,MAPMASK                 ; in preperation for masking data
  1970.     out   dx,al
  1971.     inc   dx                          ; Point dx to SC data register
  1972.     mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter
  1973.  
  1974. @@RowLoop:
  1975.     mov   cx,[VBMWidth]               ; Width in bytes across
  1976.  
  1977. @@ColumnLoop:
  1978.     lodsb
  1979.     out   dx,al
  1980.     mov   al,es:[bx]                  ; load latches from source bitmap
  1981.     stosb                             ; store latches to dest. bitmap
  1982.     inc   bx
  1983.     loop  @@ColumnLoop
  1984.  
  1985.     add   di,[NextLineIncr]           ; point to start of next dest row
  1986.     dec   ah                          ; decrement scan line counter
  1987.     jnz   @@RowLoop                   ; jump if more scanlines left
  1988.  
  1989.     mov   dx,GCINDEX+1               ; Restore bitmask to the default -
  1990.     mov   al,0ffh                     ;  all data from cpu
  1991.     out   dx,al
  1992.  
  1993.     pop   ds                          ; restore data segment
  1994.     pop   di                          ; restore registers
  1995.     pop   si
  1996.     ret
  1997. xputmaskedvbm  endp
  1998.  
  1999.  
  2000. xputmaskedvbmclipx  proc far X:word,Y:word,ScrnOffs:word,SrcVBM:dword
  2001. LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,NextLineIncr:word
  2002.     push  si
  2003.     push  di
  2004.     push  ds
  2005.     cld
  2006.  
  2007.     mov   di,[X]                  ; load X coord int DI and make a
  2008.     mov   si,di                   ;  copy in SI
  2009.     sar   di,2                    ; Find Byte offset of X coord
  2010.  
  2011.     and   si,3                    ; Calculate pixels plane alignment
  2012.     shl   si,2                    ; Prepare to lookup mask & data
  2013.     les   bx,[SrcVBM]             ; ES:BX -> begining of VBM data
  2014.  
  2015.     mov   cx,es:[bx+ImageWidth]   ; Get image width and save in CX
  2016.  
  2017.  
  2018.  
  2019.     ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2020.  
  2021.     mov   dx,[LeftClip]
  2022.     sub   dx,di
  2023.     jle   @@NotLeftClip
  2024.     cmp   dx,cx
  2025.     jnl   @@NotVisible
  2026.     add   di,dx
  2027.     mov   [LeftSkip],dx
  2028.     mov   [DataInc],dx
  2029.     sub   cx,dx
  2030.     jmp   short @@HorizClipDone
  2031.  
  2032.                 ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  2033.  
  2034. @@NotVisible:
  2035.     mov   ax,1
  2036.     pop   ds                          ; restore data segment
  2037.     pop   di                          ; restore registers
  2038.     pop   si
  2039.     ret
  2040.  
  2041.     ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2042.  
  2043. @@NotLeftClip:
  2044.     mov   dx,[RightClip]
  2045.     sub   dx,di
  2046.     js    @@NotVisible
  2047.     mov   [LeftSkip],0
  2048.     mov   [DataInc],0
  2049.     cmp   dx,cx
  2050.     jge   @@HorizClipDone
  2051.     inc   dx
  2052.     sub   cx,dx
  2053.     mov   [DataInc],cx
  2054.     mov   cx,dx
  2055.  
  2056. @@HorizClipDone:
  2057.  
  2058.  
  2059.     add   di,[ScrnOffs]           ; Add the current page offset
  2060.     mov   [VBMWidth],cx
  2061.     mov   ax,es:[bx+ImageHeight]  ; Get image height and save in AX
  2062.     mov   [VBMHeight],ax
  2063.  
  2064.  
  2065.     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2066.  
  2067.     mov   ax,[Y]                      ; Calculate dest screen row
  2068.     mov   cx,[ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen
  2069.     mul   cx                          ;  width then adding screen offset
  2070.     add   di,ax                       ; Add Dest Screen Row to di
  2071.     sub   cx,[VBMWidth]
  2072.     mov   [NextLineIncr],cx
  2073.  
  2074.     mov   ax,es                       ; copy ES to DS
  2075.     mov   dx,SCREENSEG                ; Point ES to VGA segment
  2076.     mov   ds,ax
  2077.     mov   es,dx
  2078.  
  2079.     mov   ax,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data
  2080.     mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
  2081.     mov   si,ax
  2082.  
  2083.     mov   ax,[LeftSkip]               ; Skip data/mask bytes in
  2084.     add   bx,ax                       ; each row that have been clipped
  2085.     add   si,ax                       ; by the L.H.S border
  2086.  
  2087.  
  2088.     mov   dx,GCINDEX                 ; Set bit mask for all bits from
  2089.     mov   ax,BITMASK                 ; VGA latches and none from CPU
  2090.     out   dx,ax
  2091.     mov   dx,SCINDEX                 ; Point SC register to map mask
  2092.     mov   al,MAPMASK                 ; in preperation for masking data
  2093.     out   dx,al
  2094.     inc   dx                          ; Point dx to SC data register
  2095.     mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter
  2096.  
  2097. @@RowLoop:
  2098.     mov   cx,[VBMWidth]               ; Width in bytes across
  2099.  
  2100. @@ColumnLoop:
  2101.     lodsb
  2102.     out   dx,al
  2103.     mov   al,es:[bx]                  ; load latches from source bitmap
  2104.     stosb                             ; store latches to dest. bitmap
  2105.     inc   bx
  2106.     loop  @@ColumnLoop
  2107.     add   bx,[DataInc]
  2108.     add   si,[DataInc]
  2109.     add   di,[NextLineIncr]           ; point to start of next dest row
  2110.     dec   byte ptr ah                 ; decrement scan line counter
  2111.     jnz   @@RowLoop                   ; jump if more scanlines left
  2112.  
  2113.     mov   dx,GCINDEX+1               ; Restore bitmask to the default -
  2114.     mov   al,0ffh                     ;  all data from cpu
  2115.     out   dx,al
  2116.     xor   ax,ax
  2117.     pop   ds                          ; restore data segment
  2118.     pop   di                          ; restore registers
  2119.     pop   si
  2120.     ret
  2121. xputmaskedvbmclipx  endp
  2122.  
  2123.  
  2124. xputmaskedvbmclipy  proc far X:word,Y:word,ScrnOffs:word,SrcVBM:dword
  2125. LOCAL VBMWidth,VBMHeight,TopRow,NextLineIncr:word
  2126.     push  si
  2127.     push  di
  2128.     push  ds
  2129.     cld
  2130.  
  2131.     mov   di,[X]                  ; load X coord int DI and make a
  2132.     mov   si,di                   ;  copy in SI
  2133.  
  2134.  
  2135.     and   si,3                    ; Calculate pixels plane alignment
  2136.     shl   si,2                    ; Prepare to lookup mask & data
  2137.     les   bx,[SrcVBM]             ; ES:BX -> begining of VBM data
  2138.  
  2139.  
  2140.     mov   ax,es:[bx+ImageHeight]  ; Get image height and save in AX
  2141.  
  2142.  
  2143.  
  2144.     ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  2145.  
  2146.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  2147.     sub   dx,[Y]                  ; clipping border
  2148.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  2149.     cmp   dx,ax
  2150.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  2151.     mov   [TopRow],dx
  2152.     sub   ax,dx
  2153.     add   [Y],dx
  2154.     jmp   short @@VertClipDone
  2155.  
  2156.     ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  2157.  
  2158. @@NotVisible:
  2159.     mov   ax,1
  2160.     pop   ds                          ; restore data segment
  2161.     pop   di                          ; restore registers
  2162.     pop   si
  2163.     ret
  2164.  
  2165.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2166.  
  2167. @@NotTopClip:
  2168.     mov   dx,[BottomClip]
  2169.     sub   dx,[Y]
  2170.     js    @@NotVisible
  2171.     mov   [TopRow],0
  2172.     cmp   dx,ax
  2173.     jg    @@VertClipDone
  2174.     inc   dx
  2175.     mov   ax,dx
  2176.  
  2177. @@VertClipDone:
  2178.  
  2179.  
  2180.     shr   di,2                    ; Find Byte offset of X coord
  2181.     add   di,[ScrnOffs]           ; Add the current page offset
  2182.     mov   cx,es:[bx+ImageWidth]   ; Get image width and save in CX
  2183.     mov   [VBMWidth],cx
  2184.     mov   [VBMHeight],ax
  2185.  
  2186.     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2187.  
  2188.     mov   ax,[Y]                      ; Calculate dest screen row
  2189.     mov   cx,[ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen
  2190.     mul   cx                          ;  width then adding screen offset
  2191.     add   di,ax                       ; Add Dest Screen Row to di
  2192.     sub   cx,[VBMWidth]
  2193.     mov   [NextLineIncr],cx
  2194.  
  2195.     mov   ax,es                       ; copy ES to DS
  2196.     mov   dx,SCREENSEG                ; Point ES to VGA segment
  2197.     mov   ds,ax
  2198.     mov   es,dx
  2199.  
  2200.     mov   ax,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data
  2201.     mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
  2202.     mov   si,ax
  2203.  
  2204.  
  2205.  
  2206.     mov   ax,[VBMWidth]               ; Increment DS:BX and DS:SI to
  2207.     mul   [TopRow]                    ;  skip image/mask data that has
  2208.     add   bx,ax                       ;  been clipped by the top border
  2209.     add   si,ax
  2210.  
  2211.  
  2212.     mov   dx,GCINDEX                 ; Set bit mask for all bits from
  2213.     mov   ax,BITMASK                 ; VGA latches and none from CPU
  2214.     out   dx,ax
  2215.     mov   dx,SCINDEX                 ; Point SC register to map mask
  2216.     mov   al,MAPMASK                 ; in preperation for masking data
  2217.     out   dx,al
  2218.     inc   dx                          ; Point dx to SC data register
  2219.     mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter
  2220.  
  2221. @@RowLoop:
  2222.     mov   cx,[VBMWidth]               ; Width in bytes across
  2223.  
  2224. @@ColumnLoop:
  2225.     lodsb
  2226.     out   dx,al
  2227.     mov   al,es:[bx]                  ; load latches from source bitmap
  2228.     stosb                             ; store latches to dest. bitmap
  2229.     inc   bx
  2230.     loop  @@ColumnLoop
  2231.     add   di,[NextLineIncr]           ; point to start of next dest row
  2232.     dec   byte ptr ah                 ; decrement scan line counter
  2233.     jnz   @@RowLoop                   ; jump if more scanlines left
  2234.  
  2235.     mov   dx,GCINDEX+1               ; Restore bitmask to the default -
  2236.     mov   al,0ffh                     ;  all data from cpu
  2237.     out   dx,al
  2238.  
  2239.     xor   ax,ax
  2240.     pop   ds                          ; restore data segment
  2241.     pop   di                          ; restore registers
  2242.     pop   si
  2243.     ret
  2244. xputmaskedvbmclipy  endp
  2245.  
  2246. xputmaskedvbmclipxy  proc far X:word,Y:word,ScrnOffs:word,SrcVBM:dword
  2247. LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,TopRow,NextLineIncr:word
  2248.     push  si
  2249.     push  di
  2250.     push  ds
  2251.     cld
  2252.  
  2253.     mov   di,[X]                  ; load X coord int DI and make a
  2254.     mov   si,di                   ;  copy in SI
  2255.     sar   di,2                    ; Find Byte offset of X coord
  2256.     and   si,3                    ; Calculate pixels plane alignment
  2257.     shl   si,2                    ; Prepare to lookup mask & data
  2258.     les   bx,[SrcVBM]             ; ES:BX -> begining of VBM data
  2259.  
  2260.     mov   cx,es:[bx+ImageWidth]   ; Get image width and save in CX
  2261.     mov   ax,es:[bx+ImageHeight]  ; Get image height and save in AX
  2262.  
  2263.  
  2264.  
  2265.     ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  2266.  
  2267.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  2268.     sub   dx,[Y]                  ; clipping border
  2269.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  2270.     cmp   dx,ax
  2271.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  2272.     mov   [TopRow],dx
  2273.     sub   ax,dx
  2274.     add   [Y],dx
  2275.     jmp   short @@VertClipDone
  2276.  
  2277.     ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  2278.  
  2279. @@NotVisible:
  2280.     mov   ax,1
  2281.     pop   ds                          ; restore data segment
  2282.     pop   di                          ; restore registers
  2283.     pop   si
  2284.     ret
  2285.  
  2286.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2287.  
  2288. @@NotTopClip:
  2289.     mov   dx,[BottomClip]
  2290.     sub   dx,[Y]
  2291.     js    @@NotVisible
  2292.     mov   [TopRow],0
  2293.     cmp   dx,ax
  2294.     jg    @@VertClipDone
  2295.     inc   dx
  2296.     mov   ax,dx
  2297.  
  2298. @@VertClipDone:
  2299.  
  2300.     ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2301.  
  2302.  
  2303.     mov   dx,[LeftClip]
  2304.     sub   dx,di
  2305.     jle   @@NotLeftClip
  2306.     cmp   dx,cx
  2307.     jnl   @@NotVisible
  2308.     add   di,dx
  2309.     mov   [LeftSkip],dx
  2310.     mov   [DataInc],dx
  2311.     sub   cx,dx
  2312.     jmp   short @@HorizClipDone
  2313.  
  2314.     ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2315.  
  2316. @@NotLeftClip:
  2317.     mov   dx,[RightClip]
  2318.     sub   dx,di
  2319.     js    @@NotVisible
  2320.     mov   [LeftSkip],0
  2321.     mov   [DataInc],0
  2322.     cmp   dx,cx
  2323.     jge    @@HorizClipDone
  2324.     inc   dx
  2325.     sub   cx,dx
  2326.     mov   [DataInc],cx
  2327.     mov   cx,dx
  2328.  
  2329. @@HorizClipDone:
  2330.  
  2331.     add   di,[ScrnOffs]           ; Add the current page offset
  2332.     mov   [VBMWidth],cx
  2333.     mov   [VBMHeight],ax
  2334.     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2335.  
  2336.     mov   ax,[Y]                      ; Calculate dest screen row
  2337.     mov   cx,[ScrnLogicalByteWidth]   ;  by mult. dest Y coord by Screen
  2338.     mul   cx                          ;  width then adding screen offset
  2339.     add   di,ax                       ; Add Dest Screen Row to di
  2340.     sub   cx,[VBMWidth]
  2341.     mov   [NextLineIncr],cx
  2342.  
  2343.     mov   ax,es                       ; copy ES to DS
  2344.     mov   dx,SCREENSEG                ; Point ES to VGA segment
  2345.     mov   ds,ax
  2346.     mov   es,dx
  2347.  
  2348.     mov   ax,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data
  2349.     mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
  2350.     mov   si,ax
  2351.  
  2352.  
  2353.  
  2354.     mov   ax,[VBMWidth]               ; Increment DS:BX and DS:SI to
  2355.     add   ax,[DataInc]                ;  skip image/mask data that has
  2356.     mul   [TopRow]                    ;  been clipped by the top border
  2357.     add   ax,[LeftSkip]               ; Skip also data/mask bytes in
  2358.     add   bx,ax                       ; each row that have been clipped
  2359.     add   si,ax                       ; by the L.H.S border
  2360.  
  2361.  
  2362.     mov   dx,GCINDEX                  ; Set bit mask for all bits from
  2363.     mov   ax,BITMASK                  ; VGA latches and none from CPU
  2364.     out   dx,ax
  2365.     mov   dx,SCINDEX                  ; Point SC register to map mask
  2366.     mov   al,MAPMASK                  ; in preperation for masking data
  2367.     out   dx,al
  2368.     inc   dx                          ; Point dx to SC data register
  2369.     mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter
  2370.  
  2371. @@RowLoop:
  2372.     mov   cx,[VBMWidth]               ; Width in bytes across
  2373.  
  2374. @@ColumnLoop:
  2375.     lodsb
  2376.     out   dx,al
  2377.     mov   al,es:[bx]                  ; load latches from source bitmap
  2378.     stosb                             ; store latches to dest. bitmap
  2379.     inc   bx
  2380.     loop  @@ColumnLoop
  2381.     add   bx,[DataInc]
  2382.     add   si,[DataInc]
  2383.     add   di,[NextLineIncr]           ; point to start of next dest row
  2384.     dec   byte ptr ah                 ; decrement scan line counter
  2385.     jnz   @@RowLoop                   ; jump if more scanlines left
  2386.  
  2387.     mov   dx,GCINDEX+1                ; Restore bitmask to the default -
  2388.     mov   al,0ffh                     ;  all data from cpu
  2389.     out   dx,al
  2390.     xor   ax,ax
  2391.     pop   ds                          ; restore data segment
  2392.     pop   di                          ; restore registers
  2393.     pop   si
  2394.     ret
  2395. xputmaskedvbmclipxy  endp
  2396.  
  2397. xscale PROC FAR DestX:WORD, DestY:WORD, DestWidth:WORD, DestHeight:WORD,\
  2398.                                 ScrnOffs : WORD, Bitmap:DWord
  2399.  
  2400. LOCAL   DecisionX:WORD, DecisionY:WORD, ClippedWidth:WORD, ClippedHeight:WORD,\
  2401.                 SourceWidth:WORD, SourceHeight:WORD, SourceOffset : Word,\
  2402.                 SourceWidth2 : Word, SourceHeight2 : word, ByteWidth : word,\
  2403.                 Plane : BYTE, DestWidth2 : word, DestHeight2 : word
  2404.  
  2405.                 push            ds
  2406.                 push    ds
  2407.                 lds                     si, Bitmap
  2408.                 xor     ah, ah
  2409.                 lodsb
  2410.                 mov     SourceWidth, ax
  2411.                 lodsb
  2412.                 mov     SourceHeight, ax
  2413.                 pop     ds
  2414.  
  2415.                 shl                     LeftClip, 2
  2416.                 shl     RightClip, 2
  2417.  
  2418.                 cmp     DestWidth, 2        ; If destination width is less than 2
  2419.                 jl      @@Done                ;     then don't draw it.
  2420.  
  2421.                 cmp     DestHeight, 2       ; If destination height is less than 2
  2422.                 jl      @@Done                ;     then don't draw it.
  2423.  
  2424.                 mov     ax, DestY           ; If it is completely below the
  2425.                 cmp     ax, BottomClip          ; lower clip bondry,
  2426.                 jg      @@Done                ;     then don't draw it.
  2427.  
  2428.                 add     ax, DestHeight      ; If it is above clip boundries
  2429.                 dec     ax                  ;     then don't draw it.
  2430.                 cmp     ax, TopClip
  2431.                 jl      @@Done
  2432.  
  2433.                 mov     ax, DestX           ; If it is to the right of the
  2434.                 cmp     ax, RightClip          ;     then don't draw it.
  2435.                 jg      @@Done
  2436.  
  2437.                 add     ax, DestWidth       ; If it is completely to the left
  2438.                 dec     ax                  ; of the left clip boundry,
  2439.                 cmp     ax, LeftClip          ;     then don't draw it.
  2440.                 jl      @@Done
  2441.  
  2442.                 mov     ax, DestWidth
  2443.                 mov     ClippedWidth, ax
  2444.  
  2445.                 shl     ax,1                ; Initialize the X decision var
  2446.                 neg     ax                  ; to be -2*DestWidth
  2447.                 mov     DecisionX, ax       ;
  2448.  
  2449.                 mov     ax, DestHeight      ; ClippedHeight is initially set to
  2450.                 mov     ClippedHeight, ax   ; the requested dest size.
  2451.  
  2452.                 shl     ax,1                ; Initialize the Y decision var
  2453.                 neg     ax                  ; to be -2*DestHeight
  2454.                 mov     DecisionY, ax       ;
  2455.  
  2456.                 mov                     SourceOffset, 0
  2457.  
  2458.                 movsx   eax, TopClip        ; If Y is below the top
  2459.                 mov     edx, eax            ; clipping boundry, then we don't
  2460.                 sub     dx, DestY           ; need to clip the top, so we can
  2461.                 js      @@NoTopClip         ; jump over the clipping stuff.
  2462.  
  2463.                 mov     DestY, ax           ; This block performs clipping on the
  2464.                 sub     ClippedHeight, dx   ; top of the bitmap.  I have heavily
  2465.                 movsx   ecx, SourceHeight   ; optimized this block to use only 4
  2466.                 imul    ecx, edx            ; 32-bit registers, so I'm not even
  2467.                 mov     eax, ecx            ; gonna try to explain what it's doing.
  2468.                 mov     edx, 0              ; But I can tell you what results from
  2469.                 movsx   ebx, DestHeight     ; this:  The DecisionY var is updated
  2470.                 idiv    ebx                 ; to start at the right clipped row.
  2471.                 movsx   edx, SourceWidth    ; Y is moved to the top clip
  2472.                 imul    edx, eax            ; boundry. ClippedHeight is lowered since
  2473.                 add     si, dx              ; we won't be drawing all the requested
  2474.                 imul    eax, ebx            ; rows.  SI is changed to point over
  2475.                 sub     ecx, eax            ; the bitmap data that is clipped off.
  2476.                 sub     ecx, ebx            ;
  2477.                 shl     ecx, 1              ;
  2478.                 mov     DecisionY, cx       ; <end of top clipping block >
  2479.  
  2480. @@NoTopClip:
  2481.                 mov     ax, DestY           ; If the bitmap doesn't extend over the
  2482.                 add     ax, ClippedHeight   ; bottom clipping boundry, then we
  2483.                 dec     ax                  ; don't need to clip the bottom, so we
  2484.                 cmp     ax, BottomClip      ; can jump over the bottom clip code.
  2485.                 jle     @@NoBottomClip      ;
  2486.  
  2487.                 mov     ax, BottomClip      ; Clip off the bottom by reducing the
  2488.                 sub     ax, DestY           ; ClippedHeight so that the bitmap won't
  2489.                 inc     ax                  ; extend over the lower clipping
  2490.                 mov     ClippedHeight, ax   ; boundry.
  2491.  
  2492. @@NoBottomClip:
  2493.                 movsx   eax, LeftClip       ; If X is to the left of the
  2494.                 mov     edx, eax            ; top clipping boundry, then we don't
  2495.                 sub     dx, DestX           ; need to clip the left, so we can
  2496.                 js      @@NoLeftClip        ; jump over the clipping stuff.
  2497.  
  2498.                 mov     DestX, ax           ; This block performs clipping on the
  2499.                 sub     ClippedWidth, dx    ; left of the bitmap.  I have heavily
  2500.                 movsx   ecx, SourceWidth    ; optimized this block to use only 4
  2501.                 imul    ecx, edx            ; 32-bit registers, so I'm not even
  2502.                 mov     eax, ecx            ; gonna try to explain what it's doing.
  2503.                 mov     edx, 0              ; But I can tell you what results from
  2504.                 movsx   ebx, DestWidth      ; this:  The DecisionX var is updated
  2505.                 idiv    ebx                 ; to start at the right clipped column.
  2506.                 add     SourceOffset, ax    ; X is moved to the left clip
  2507.                 imul    eax, ebx            ; boundry. ClippedWidth is reduced since
  2508.                 sub     ecx, eax            ; we won't be drawing all the requested
  2509.                 sub     ecx, ebx            ; cols.  SI is changed to point over
  2510.                 shl     ecx, 1              ; the bitmap data that is clipped off.
  2511.                 mov     DecisionX, cx       ; <end of left clipping block >
  2512.  
  2513. @@NoLeftClip:
  2514.                 mov     ax, DestX           ; If the bitmap doesn't extend over the
  2515.                 add     ax, ClippedWidth    ; right clipping boundry, then we
  2516.                 dec     ax                  ; don't need to clip the right, so we
  2517.                 cmp     ax, RightClip       ; can jump over the right clip code.
  2518.                 jle     @@NoClipRight       ;
  2519.  
  2520.                 mov     ax, RightClip       ; Clip off the right by reducing the
  2521.                 sub     ax, DestX           ; ClippedWidth so that the bitmap won't
  2522.                 inc     ax                  ; extend over the right clipping
  2523.                 mov     ClippedWidth, ax    ; boundry.
  2524.  
  2525.                 ;Calculate starting video address
  2526. @@NoClipRight:
  2527.                 mov                     ax, SourceWidth
  2528.                 shl     ax, 1
  2529.                 mov     SourceWidth2, ax
  2530.  
  2531.                 mov     ax, SourceHeight
  2532.                 shl     ax, 1
  2533.                 mov     SourceHeight2, ax
  2534.  
  2535.                 mov     ax, DestHeight
  2536.                 shl     ax, 1
  2537.                 mov     DestHeight2, ax
  2538.  
  2539.                 mov     ax, DestWidth
  2540.                 shl     ax, 1
  2541.                 mov     DestWidth2, ax
  2542.  
  2543.                 mov                     ax, ScrnLogicalByteWidth
  2544.                 mov     ByteWidth, ax
  2545.  
  2546.                 mov     ax, SCREENSEG
  2547.                 mov     es, ax
  2548.                 mov     ax, DestY
  2549.                 mov     bx, ScrnLogicalByteWidth
  2550.                 mul     bx
  2551.                 mov     di, ScrnOffs
  2552.                 add     di, ax
  2553.  
  2554.                 mov     cx, DestX
  2555.                 mov     dx, cx
  2556.                 shr     dx, 2
  2557.                 add     di, dx
  2558.  
  2559.                 lds     si, Bitmap
  2560.                 add     si, 2
  2561.                 add     si, SourceOffset
  2562.  
  2563.                 mov     dx, SCINDEX         ; Point the VGA Sequencer to the Map
  2564.                 mov     al, MAPMASK         ; Mask register, so that we only need
  2565.                 out     dx, al              ; to send out 1 byte per column.
  2566.  
  2567.                 inc     dx                  ; Move to the Sequencer's Data register.
  2568.                 and     cx, 3               ; Calculate the starting plane. This is
  2569.                 mov     al, 11h             ; just:
  2570.                 shl     al, cl              ; Plane =  (11h << (X AND 3))
  2571.                 mov     Plane, al
  2572.                 out     dx, al              ; Select the first plane.
  2573.  
  2574. @@RowLoop:
  2575.                 push    si                  ; Save the starting source index
  2576.                 push    di                  ; Save the starting dest index
  2577.  
  2578.                 mov     cx, ClippedHeight
  2579.                 mov     bx, DecisionY
  2580.                 mov     dx, ByteWidth
  2581.  
  2582.                 mov     al, ds:[si]
  2583.  
  2584. @@ColumnLoop:
  2585.                 mov     es:[di], al
  2586.                 add     di, dx
  2587.                 dec     cx
  2588.                 jz      @@DoneWithCol
  2589.                 add     bx, SourceHeight2
  2590.                 js      @@ColumnLoop
  2591.  
  2592. @@IncSourceRow:
  2593.                 add     si, SourceWidth
  2594.                 sub     bx, DestHeight2
  2595.                 jns     @@IncSourceRow
  2596.                 mov     al, ds:[si]
  2597.                 jmp     @@ColumnLoop
  2598.  
  2599. @@DoneWithCol:
  2600.                 pop     di
  2601.                 pop     si
  2602.  
  2603.                 rol     Plane, 1
  2604.                 adc     di, 0
  2605.                 mov     dx, SCINDEX
  2606.                 inc     dx
  2607.                 mov     al, Plane
  2608.                 out     dx, al
  2609.  
  2610.                 mov     ax, SourceWidth2
  2611.                 add     DecisionX, ax
  2612.                 js      @@NextCol
  2613. @@IncSourceCol:
  2614.                 inc     si
  2615.                 mov     ax, DestWidth2
  2616.                 sub     DecisionX, ax
  2617.                 jns     @@IncSourceCol
  2618. @@NextCol:
  2619.                 dec     ClippedWidth        ; If we're not at last column
  2620.                 jnz     @@RowLoop           ;    then do another column
  2621. @@Done:
  2622.                 pop     ds
  2623.                 shr                     LeftClip, 2
  2624.                 shr     RightClip, 2
  2625.                 ret                         ; We're done!
  2626.  
  2627. xscale     ENDP
  2628.  
  2629. xmaskedscale PROC FAR DestX:WORD, DestY:WORD, DestWidth:WORD, DestHeight:WORD,\
  2630.                                 ScrnOffs : WORD, Bitmap:DWord
  2631.  
  2632. LOCAL   DecisionX:WORD, DecisionY:WORD, ClippedWidth:WORD, ClippedHeight:WORD,\
  2633.                 SourceWidth:WORD, SourceHeight:WORD, SourceOffset : Word,\
  2634.                 SourceWidth2 : Word, SourceHeight2 : word, ByteWidth : word,\
  2635.                 Plane : BYTE, DestWidth2 : word, DestHeight2 : word
  2636.  
  2637.                 push            ds
  2638.                 push    ds
  2639.                 lds                     si, Bitmap
  2640.                 xor     ah, ah
  2641.                 lodsb
  2642.                 mov     SourceWidth, ax
  2643.                 lodsb
  2644.                 mov     SourceHeight, ax
  2645.                 pop     ds
  2646.  
  2647.                 shl                     LeftClip, 2
  2648.                 shl     RightClip, 2
  2649.  
  2650.                 cmp     DestWidth, 2        ; If destination width is less than 2
  2651.                 jl      @@Done                ;     then don't draw it.
  2652.  
  2653.                 cmp     DestHeight, 2       ; If destination height is less than 2
  2654.                 jl      @@Done                ;     then don't draw it.
  2655.  
  2656.                 mov     ax, DestY           ; If it is completely below the
  2657.                 cmp     ax, BottomClip          ; lower clip bondry,
  2658.                 jg      @@Done                ;     then don't draw it.
  2659.  
  2660.                 add     ax, DestHeight      ; If it is above clip boundries
  2661.                 dec     ax                  ;     then don't draw it.
  2662.                 cmp     ax, TopClip
  2663.                 jl      @@Done
  2664.  
  2665.                 mov     ax, DestX           ; If it is to the right of the
  2666.                 cmp     ax, RightClip          ;     then don't draw it.
  2667.                 jg      @@Done
  2668.  
  2669.                 add     ax, DestWidth       ; If it is completely to the left
  2670.                 dec     ax                  ; of the left clip boundry,
  2671.                 cmp     ax, LeftClip          ;     then don't draw it.
  2672.                 jl      @@Done
  2673.  
  2674.                 mov     ax, DestWidth
  2675.                 mov     ClippedWidth, ax
  2676.  
  2677.                 shl     ax,1                ; Initialize the X decision var
  2678.                 neg     ax                  ; to be -2*DestWidth
  2679.                 mov     DecisionX, ax       ;
  2680.  
  2681.                 mov     ax, DestHeight      ; ClippedHeight is initially set to
  2682.                 mov     ClippedHeight, ax   ; the requested dest size.
  2683.  
  2684.                 shl     ax,1                ; Initialize the Y decision var
  2685.                 neg     ax                  ; to be -2*DestHeight
  2686.                 mov     DecisionY, ax       ;
  2687.  
  2688.                 mov                     SourceOffset, 0
  2689.  
  2690.                 movsx   eax, TopClip        ; If Y is below the top
  2691.                 mov     edx, eax            ; clipping boundry, then we don't
  2692.                 sub     dx, DestY           ; need to clip the top, so we can
  2693.                 js      @@NoTopClip         ; jump over the clipping stuff.
  2694.  
  2695.                 mov     DestY, ax           ; This block performs clipping on the
  2696.                 sub     ClippedHeight, dx   ; top of the bitmap.  I have heavily
  2697.                 movsx   ecx, SourceHeight   ; optimized this block to use only 4
  2698.                 imul    ecx, edx            ; 32-bit registers, so I'm not even
  2699.                 mov     eax, ecx            ; gonna try to explain what it's doing.
  2700.                 mov     edx, 0              ; But I can tell you what results from
  2701.                 movsx   ebx, DestHeight     ; this:  The DecisionY var is updated
  2702.                 idiv    ebx                 ; to start at the right clipped row.
  2703.                 movsx   edx, SourceWidth    ; Y is moved to the top clip
  2704.                 imul    edx, eax            ; boundry. ClippedHeight is lowered since
  2705.                 add     si, dx              ; we won't be drawing all the requested
  2706.                 imul    eax, ebx            ; rows.  SI is changed to point over
  2707.                 sub     ecx, eax            ; the bitmap data that is clipped off.
  2708.                 sub     ecx, ebx            ;
  2709.                 shl     ecx, 1              ;
  2710.                 mov     DecisionY, cx       ; <end of top clipping block >
  2711.  
  2712. @@NoTopClip:
  2713.                 mov     ax, DestY           ; If the bitmap doesn't extend over the
  2714.                 add     ax, ClippedHeight   ; bottom clipping boundry, then we
  2715.                 dec     ax                  ; don't need to clip the bottom, so we
  2716.                 cmp     ax, BottomClip      ; can jump over the bottom clip code.
  2717.                 jle     @@NoBottomClip      ;
  2718.  
  2719.                 mov     ax, BottomClip      ; Clip off the bottom by reducing the
  2720.                 sub     ax, DestY           ; ClippedHeight so that the bitmap won't
  2721.                 inc     ax                  ; extend over the lower clipping
  2722.                 mov     ClippedHeight, ax   ; boundry.
  2723.  
  2724. @@NoBottomClip:
  2725.                 movsx   eax, LeftClip       ; If X is to the left of the
  2726.                 mov     edx, eax            ; top clipping boundry, then we don't
  2727.                 sub     dx, DestX           ; need to clip the left, so we can
  2728.                 js      @@NoLeftClip        ; jump over the clipping stuff.
  2729.  
  2730.                 mov     DestX, ax           ; This block performs clipping on the
  2731.                 sub     ClippedWidth, dx    ; left of the bitmap.  I have heavily
  2732.                 movsx   ecx, SourceWidth    ; optimized this block to use only 4
  2733.                 imul    ecx, edx            ; 32-bit registers, so I'm not even
  2734.                 mov     eax, ecx            ; gonna try to explain what it's doing.
  2735.                 mov     edx, 0              ; But I can tell you what results from
  2736.                 movsx   ebx, DestWidth      ; this:  The DecisionX var is updated
  2737.                 idiv    ebx                 ; to start at the right clipped column.
  2738.                 add     SourceOffset, ax    ; X is moved to the left clip
  2739.                 imul    eax, ebx            ; boundry. ClippedWidth is reduced since
  2740.                 sub     ecx, eax            ; we won't be drawing all the requested
  2741.                 sub     ecx, ebx            ; cols.  SI is changed to point over
  2742.                 shl     ecx, 1              ; the bitmap data that is clipped off.
  2743.                 mov     DecisionX, cx       ; <end of left clipping block >
  2744.  
  2745. @@NoLeftClip:
  2746.                 mov     ax, DestX           ; If the bitmap doesn't extend over the
  2747.                 add     ax, ClippedWidth    ; right clipping boundry, then we
  2748.                 dec     ax                  ; don't need to clip the right, so we
  2749.                 cmp     ax, RightClip       ; can jump over the right clip code.
  2750.                 jle     @@NoClipRight       ;
  2751.  
  2752.                 mov     ax, RightClip       ; Clip off the right by reducing the
  2753.                 sub     ax, DestX           ; ClippedWidth so that the bitmap won't
  2754.                 inc     ax                  ; extend over the right clipping
  2755.                 mov     ClippedWidth, ax    ; boundry.
  2756.  
  2757.                 ;Calculate starting video address
  2758. @@NoClipRight:
  2759.                 mov                     ax, SourceWidth
  2760.                 shl     ax, 1
  2761.                 mov     SourceWidth2, ax
  2762.  
  2763.                 mov     ax, SourceHeight
  2764.                 shl     ax, 1
  2765.                 mov     SourceHeight2, ax
  2766.  
  2767.                 mov     ax, DestHeight
  2768.                 shl     ax, 1
  2769.                 mov     DestHeight2, ax
  2770.  
  2771.                 mov     ax, DestWidth
  2772.                 shl     ax, 1
  2773.                 mov     DestWidth2, ax
  2774.  
  2775.                 mov                     ax, ScrnLogicalByteWidth
  2776.                 mov     ByteWidth, ax
  2777.  
  2778.                 mov     ax, SCREENSEG
  2779.                 mov     es, ax
  2780.                 mov     ax, DestY
  2781.                 mov     bx, ScrnLogicalByteWidth
  2782.                 mul     bx
  2783.                 mov     di, ScrnOffs
  2784.                 add     di, ax
  2785.  
  2786.                 mov     cx, DestX
  2787.                 mov     dx, cx
  2788.                 shr     dx, 2
  2789.                 add     di, dx
  2790.  
  2791.                 lds     si, Bitmap
  2792.                 add     si, 2
  2793.                 add     si, SourceOffset
  2794.  
  2795.                 mov     dx, SCINDEX         ; Point the VGA Sequencer to the Map
  2796.                 mov     al, MAPMASK         ; Mask register, so that we only need
  2797.                 out     dx, al              ; to send out 1 byte per column.
  2798.  
  2799.                 inc     dx                  ; Move to the Sequencer's Data register.
  2800.                 and     cx, 3               ; Calculate the starting plane. This is
  2801.                 mov     al, 11h             ; just:
  2802.                 shl     al, cl              ; Plane =  (11h << (X AND 3))
  2803.                 mov     Plane, al
  2804.                 out     dx, al              ; Select the first plane.
  2805.  
  2806. @@RowLoop:
  2807.                 push    si                  ; Save the starting source index
  2808.                 push    di                  ; Save the starting dest index
  2809.  
  2810.                 mov     cx, ClippedHeight
  2811.                 mov     bx, DecisionY
  2812.                 mov     dx, ByteWidth
  2813.  
  2814.                 mov     al, ds:[si]
  2815.  
  2816. @@ColumnLoop:
  2817.                 or      al, al
  2818.                 jz      @@DontDraw
  2819.                 mov     es:[di], al
  2820. @@DontDraw:
  2821.                 add     di, dx
  2822.                 dec     cx
  2823.                 jz      @@DoneWithCol
  2824.                 add     bx, SourceHeight2
  2825.                 js      @@ColumnLoop
  2826.  
  2827. @@IncSourceRow:
  2828.                 add     si, SourceWidth
  2829.                 sub     bx, DestHeight2
  2830.                 jns     @@IncSourceRow
  2831.                 mov     al, ds:[si]
  2832.                 jmp     @@ColumnLoop
  2833.  
  2834. @@DoneWithCol:
  2835.                 pop     di
  2836.                 pop     si
  2837.  
  2838.                 rol     Plane, 1
  2839.                 adc     di, 0
  2840.                 mov     dx, SCINDEX
  2841.                 inc     dx
  2842.                 mov     al, Plane
  2843.                 out     dx, al
  2844.  
  2845.                 mov     ax, SourceWidth2
  2846.                 add     DecisionX, ax
  2847.                 js      @@NextCol
  2848. @@IncSourceCol:
  2849.                 inc     si
  2850.                 mov     ax, DestWidth2
  2851.                 sub     DecisionX, ax
  2852.                 jns     @@IncSourceCol
  2853. @@NextCol:
  2854.                 dec     ClippedWidth        ; If we're not at last column
  2855.                 jnz     @@RowLoop           ;    then do another column
  2856. @@Done:
  2857.                 pop     ds
  2858.                 shr                     LeftClip, 2
  2859.                 shr     RightClip, 2
  2860.                 ret                         ; We're done!
  2861.  
  2862. xmaskedscale     ENDP
  2863.  
  2864. end
  2865.